xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- PPCISelDAGToDAG.cpp - PPC --pattern matching inst selector --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines a pattern matching instruction selector for PowerPC,
100b57cec5SDimitry Andric // converting from a legalized dag to a PPC dag.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/PPCPredicates.h"
160b57cec5SDimitry Andric #include "PPC.h"
170b57cec5SDimitry Andric #include "PPCISelLowering.h"
180b57cec5SDimitry Andric #include "PPCMachineFunctionInfo.h"
190b57cec5SDimitry Andric #include "PPCSubtarget.h"
200b57cec5SDimitry Andric #include "PPCTargetMachine.h"
210b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
2206c3fb27SDimitry Andric #include "llvm/ADT/APSInt.h"
230b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
240b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
260b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
270b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
280b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
3281ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
350b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
360b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
370b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGISel.h"
380b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
390b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
400b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
410b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
42*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
430b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
440b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
450b57cec5SDimitry Andric #include "llvm/IR/Function.h"
460b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
470b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
480b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
49e8d8bef9SDimitry Andric #include "llvm/IR/IntrinsicsPowerPC.h"
500b57cec5SDimitry Andric #include "llvm/IR/Module.h"
510b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
520b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
530b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
540b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
550b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
560b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
570b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h"
580b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
590b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
600b57cec5SDimitry Andric #include <algorithm>
610b57cec5SDimitry Andric #include <cassert>
620b57cec5SDimitry Andric #include <cstdint>
630b57cec5SDimitry Andric #include <iterator>
640b57cec5SDimitry Andric #include <limits>
650b57cec5SDimitry Andric #include <memory>
660b57cec5SDimitry Andric #include <new>
670b57cec5SDimitry Andric #include <tuple>
680b57cec5SDimitry Andric #include <utility>
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric using namespace llvm;
710b57cec5SDimitry Andric 
72bdd1243dSDimitry Andric #define DEBUG_TYPE "ppc-isel"
73bdd1243dSDimitry Andric #define PASS_NAME "PowerPC DAG->DAG Pattern Instruction Selection"
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric STATISTIC(NumSextSetcc,
760b57cec5SDimitry Andric           "Number of (sext(setcc)) nodes expanded into GPR sequence.");
770b57cec5SDimitry Andric STATISTIC(NumZextSetcc,
780b57cec5SDimitry Andric           "Number of (zext(setcc)) nodes expanded into GPR sequence.");
790b57cec5SDimitry Andric STATISTIC(SignExtensionsAdded,
800b57cec5SDimitry Andric           "Number of sign extensions for compare inputs added.");
810b57cec5SDimitry Andric STATISTIC(ZeroExtensionsAdded,
820b57cec5SDimitry Andric           "Number of zero extensions for compare inputs added.");
830b57cec5SDimitry Andric STATISTIC(NumLogicOpsOnComparison,
840b57cec5SDimitry Andric           "Number of logical ops on i1 values calculated in GPR.");
850b57cec5SDimitry Andric STATISTIC(OmittedForNonExtendUses,
860b57cec5SDimitry Andric           "Number of compares not eliminated as they have non-extending uses.");
870b57cec5SDimitry Andric STATISTIC(NumP9Setb,
880b57cec5SDimitry Andric           "Number of compares lowered to setb.");
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric // FIXME: Remove this once the bug has been fixed!
910b57cec5SDimitry Andric cl::opt<bool> ANDIGlueBug("expose-ppc-andi-glue-bug",
920b57cec5SDimitry Andric cl::desc("expose the ANDI glue bug on PPC"), cl::Hidden);
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric static cl::opt<bool>
950b57cec5SDimitry Andric     UseBitPermRewriter("ppc-use-bit-perm-rewriter", cl::init(true),
960b57cec5SDimitry Andric                        cl::desc("use aggressive ppc isel for bit permutations"),
970b57cec5SDimitry Andric                        cl::Hidden);
980b57cec5SDimitry Andric static cl::opt<bool> BPermRewriterNoMasking(
990b57cec5SDimitry Andric     "ppc-bit-perm-rewriter-stress-rotates",
1000b57cec5SDimitry Andric     cl::desc("stress rotate selection in aggressive ppc isel for "
1010b57cec5SDimitry Andric              "bit permutations"),
1020b57cec5SDimitry Andric     cl::Hidden);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric static cl::opt<bool> EnableBranchHint(
1050b57cec5SDimitry Andric   "ppc-use-branch-hint", cl::init(true),
1060b57cec5SDimitry Andric     cl::desc("Enable static hinting of branches on ppc"),
1070b57cec5SDimitry Andric     cl::Hidden);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric static cl::opt<bool> EnableTLSOpt(
1100b57cec5SDimitry Andric   "ppc-tls-opt", cl::init(true),
1110b57cec5SDimitry Andric     cl::desc("Enable tls optimization peephole"),
1120b57cec5SDimitry Andric     cl::Hidden);
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric enum ICmpInGPRType { ICGPR_All, ICGPR_None, ICGPR_I32, ICGPR_I64,
1150b57cec5SDimitry Andric   ICGPR_NonExtIn, ICGPR_Zext, ICGPR_Sext, ICGPR_ZextI32,
1160b57cec5SDimitry Andric   ICGPR_SextI32, ICGPR_ZextI64, ICGPR_SextI64 };
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric static cl::opt<ICmpInGPRType> CmpInGPR(
1190b57cec5SDimitry Andric   "ppc-gpr-icmps", cl::Hidden, cl::init(ICGPR_All),
1200b57cec5SDimitry Andric   cl::desc("Specify the types of comparisons to emit GPR-only code for."),
1210b57cec5SDimitry Andric   cl::values(clEnumValN(ICGPR_None, "none", "Do not modify integer comparisons."),
1220b57cec5SDimitry Andric              clEnumValN(ICGPR_All, "all", "All possible int comparisons in GPRs."),
1230b57cec5SDimitry Andric              clEnumValN(ICGPR_I32, "i32", "Only i32 comparisons in GPRs."),
1240b57cec5SDimitry Andric              clEnumValN(ICGPR_I64, "i64", "Only i64 comparisons in GPRs."),
1250b57cec5SDimitry Andric              clEnumValN(ICGPR_NonExtIn, "nonextin",
1260b57cec5SDimitry Andric                         "Only comparisons where inputs don't need [sz]ext."),
1270b57cec5SDimitry Andric              clEnumValN(ICGPR_Zext, "zext", "Only comparisons with zext result."),
1280b57cec5SDimitry Andric              clEnumValN(ICGPR_ZextI32, "zexti32",
1290b57cec5SDimitry Andric                         "Only i32 comparisons with zext result."),
1300b57cec5SDimitry Andric              clEnumValN(ICGPR_ZextI64, "zexti64",
1310b57cec5SDimitry Andric                         "Only i64 comparisons with zext result."),
1320b57cec5SDimitry Andric              clEnumValN(ICGPR_Sext, "sext", "Only comparisons with sext result."),
1330b57cec5SDimitry Andric              clEnumValN(ICGPR_SextI32, "sexti32",
1340b57cec5SDimitry Andric                         "Only i32 comparisons with sext result."),
1350b57cec5SDimitry Andric              clEnumValN(ICGPR_SextI64, "sexti64",
1360b57cec5SDimitry Andric                         "Only i64 comparisons with sext result.")));
1370b57cec5SDimitry Andric namespace {
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   //===--------------------------------------------------------------------===//
1400b57cec5SDimitry Andric   /// PPCDAGToDAGISel - PPC specific code to select PPC machine
1410b57cec5SDimitry Andric   /// instructions for SelectionDAG operations.
1420b57cec5SDimitry Andric   ///
1430b57cec5SDimitry Andric   class PPCDAGToDAGISel : public SelectionDAGISel {
1440b57cec5SDimitry Andric     const PPCTargetMachine &TM;
1455ffd83dbSDimitry Andric     const PPCSubtarget *Subtarget = nullptr;
146480093f4SDimitry Andric     const PPCTargetLowering *PPCLowering = nullptr;
147480093f4SDimitry Andric     unsigned GlobalBaseReg = 0;
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   public:
150bdd1243dSDimitry Andric     PPCDAGToDAGISel() = delete;
151bdd1243dSDimitry Andric 
PPCDAGToDAGISel(PPCTargetMachine & tm,CodeGenOptLevel OptLevel)1525f757f3fSDimitry Andric     explicit PPCDAGToDAGISel(PPCTargetMachine &tm, CodeGenOptLevel OptLevel)
153*0fca6ea1SDimitry Andric         : SelectionDAGISel(tm, OptLevel), TM(tm) {}
1540b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)1550b57cec5SDimitry Andric     bool runOnMachineFunction(MachineFunction &MF) override {
1560b57cec5SDimitry Andric       // Make sure we re-emit a set of the global base reg if necessary
1570b57cec5SDimitry Andric       GlobalBaseReg = 0;
1585ffd83dbSDimitry Andric       Subtarget = &MF.getSubtarget<PPCSubtarget>();
1595ffd83dbSDimitry Andric       PPCLowering = Subtarget->getTargetLowering();
160fe6060f1SDimitry Andric       if (Subtarget->hasROPProtect()) {
161fe6060f1SDimitry Andric         // Create a place on the stack for the ROP Protection Hash.
162fe6060f1SDimitry Andric         // The ROP Protection Hash will always be 8 bytes and aligned to 8
163fe6060f1SDimitry Andric         // bytes.
164fe6060f1SDimitry Andric         MachineFrameInfo &MFI = MF.getFrameInfo();
165fe6060f1SDimitry Andric         PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
166fe6060f1SDimitry Andric         const int Result = MFI.CreateStackObject(8, Align(8), false);
167fe6060f1SDimitry Andric         FI->setROPProtectionHashSaveIndex(Result);
168fe6060f1SDimitry Andric       }
1690b57cec5SDimitry Andric       SelectionDAGISel::runOnMachineFunction(MF);
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric       return true;
1720b57cec5SDimitry Andric     }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     void PreprocessISelDAG() override;
1750b57cec5SDimitry Andric     void PostprocessISelDAG() override;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric     /// getI16Imm - Return a target constant with the specified value, of type
1780b57cec5SDimitry Andric     /// i16.
getI16Imm(unsigned Imm,const SDLoc & dl)1790b57cec5SDimitry Andric     inline SDValue getI16Imm(unsigned Imm, const SDLoc &dl) {
1800b57cec5SDimitry Andric       return CurDAG->getTargetConstant(Imm, dl, MVT::i16);
1810b57cec5SDimitry Andric     }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric     /// getI32Imm - Return a target constant with the specified value, of type
1840b57cec5SDimitry Andric     /// i32.
getI32Imm(unsigned Imm,const SDLoc & dl)1850b57cec5SDimitry Andric     inline SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
1860b57cec5SDimitry Andric       return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
1870b57cec5SDimitry Andric     }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric     /// getI64Imm - Return a target constant with the specified value, of type
1900b57cec5SDimitry Andric     /// i64.
getI64Imm(uint64_t Imm,const SDLoc & dl)1910b57cec5SDimitry Andric     inline SDValue getI64Imm(uint64_t Imm, const SDLoc &dl) {
1920b57cec5SDimitry Andric       return CurDAG->getTargetConstant(Imm, dl, MVT::i64);
1930b57cec5SDimitry Andric     }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric     /// getSmallIPtrImm - Return a target constant of pointer type.
getSmallIPtrImm(uint64_t Imm,const SDLoc & dl)19681ad6265SDimitry Andric     inline SDValue getSmallIPtrImm(uint64_t Imm, const SDLoc &dl) {
1970b57cec5SDimitry Andric       return CurDAG->getTargetConstant(
1980b57cec5SDimitry Andric           Imm, dl, PPCLowering->getPointerTy(CurDAG->getDataLayout()));
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     /// isRotateAndMask - Returns true if Mask and Shift can be folded into a
2020b57cec5SDimitry Andric     /// rotate and mask opcode and mask operation.
2030b57cec5SDimitry Andric     static bool isRotateAndMask(SDNode *N, unsigned Mask, bool isShiftMask,
2040b57cec5SDimitry Andric                                 unsigned &SH, unsigned &MB, unsigned &ME);
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric     /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
2070b57cec5SDimitry Andric     /// base register.  Return the virtual register that holds this value.
2080b57cec5SDimitry Andric     SDNode *getGlobalBaseReg();
2090b57cec5SDimitry Andric 
21081ad6265SDimitry Andric     void selectFrameIndex(SDNode *SN, SDNode *N, uint64_t Offset = 0);
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric     // Select - Convert the specified operand from a target-independent to a
2130b57cec5SDimitry Andric     // target-specific node if it hasn't already been changed.
2140b57cec5SDimitry Andric     void Select(SDNode *N) override;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric     bool tryBitfieldInsert(SDNode *N);
2170b57cec5SDimitry Andric     bool tryBitPermutation(SDNode *N);
2180b57cec5SDimitry Andric     bool tryIntCompareInGPR(SDNode *N);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric     // tryTLSXFormLoad - Convert an ISD::LOAD fed by a PPCISD::ADD_TLS into
2210b57cec5SDimitry Andric     // an X-Form load instruction with the offset being a relocation coming from
2220b57cec5SDimitry Andric     // the PPCISD::ADD_TLS.
2230b57cec5SDimitry Andric     bool tryTLSXFormLoad(LoadSDNode *N);
2240b57cec5SDimitry Andric     // tryTLSXFormStore - Convert an ISD::STORE fed by a PPCISD::ADD_TLS into
2250b57cec5SDimitry Andric     // an X-Form store instruction with the offset being a relocation coming from
2260b57cec5SDimitry Andric     // the PPCISD::ADD_TLS.
2270b57cec5SDimitry Andric     bool tryTLSXFormStore(StoreSDNode *N);
2280b57cec5SDimitry Andric     /// SelectCC - Select a comparison of the specified values with the
2290b57cec5SDimitry Andric     /// specified condition code, returning the CR# of the expression.
2300b57cec5SDimitry Andric     SDValue SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
231e8d8bef9SDimitry Andric                      const SDLoc &dl, SDValue Chain = SDValue());
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric     /// SelectAddrImmOffs - Return true if the operand is valid for a preinc
2340b57cec5SDimitry Andric     /// immediate field.  Note that the operand at this point is already the
2350b57cec5SDimitry Andric     /// result of a prior SelectAddressRegImm call.
SelectAddrImmOffs(SDValue N,SDValue & Out) const2360b57cec5SDimitry Andric     bool SelectAddrImmOffs(SDValue N, SDValue &Out) const {
2370b57cec5SDimitry Andric       if (N.getOpcode() == ISD::TargetConstant ||
2380b57cec5SDimitry Andric           N.getOpcode() == ISD::TargetGlobalAddress) {
2390b57cec5SDimitry Andric         Out = N;
2400b57cec5SDimitry Andric         return true;
2410b57cec5SDimitry Andric       }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric       return false;
2440b57cec5SDimitry Andric     }
2450b57cec5SDimitry Andric 
246fe6060f1SDimitry Andric     /// SelectDSForm - Returns true if address N can be represented by the
247fe6060f1SDimitry Andric     /// addressing mode of DSForm instructions (a base register, plus a signed
248fe6060f1SDimitry Andric     /// 16-bit displacement that is a multiple of 4.
SelectDSForm(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)249fe6060f1SDimitry Andric     bool SelectDSForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
250fe6060f1SDimitry Andric       return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
251fe6060f1SDimitry Andric                                                 Align(4)) == PPC::AM_DSForm;
252fe6060f1SDimitry Andric     }
253fe6060f1SDimitry Andric 
254fe6060f1SDimitry Andric     /// SelectDQForm - Returns true if address N can be represented by the
255fe6060f1SDimitry Andric     /// addressing mode of DQForm instructions (a base register, plus a signed
256fe6060f1SDimitry Andric     /// 16-bit displacement that is a multiple of 16.
SelectDQForm(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)257fe6060f1SDimitry Andric     bool SelectDQForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
258fe6060f1SDimitry Andric       return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
259fe6060f1SDimitry Andric                                                 Align(16)) == PPC::AM_DQForm;
260fe6060f1SDimitry Andric     }
261fe6060f1SDimitry Andric 
262fe6060f1SDimitry Andric     /// SelectDForm - Returns true if address N can be represented by
263fe6060f1SDimitry Andric     /// the addressing mode of DForm instructions (a base register, plus a
264fe6060f1SDimitry Andric     /// signed 16-bit immediate.
SelectDForm(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)265fe6060f1SDimitry Andric     bool SelectDForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
266fe6060f1SDimitry Andric       return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
267bdd1243dSDimitry Andric                                                 std::nullopt) == PPC::AM_DForm;
268fe6060f1SDimitry Andric     }
269fe6060f1SDimitry Andric 
270349cc55cSDimitry Andric     /// SelectPCRelForm - Returns true if address N can be represented by
271349cc55cSDimitry Andric     /// PC-Relative addressing mode.
SelectPCRelForm(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)272349cc55cSDimitry Andric     bool SelectPCRelForm(SDNode *Parent, SDValue N, SDValue &Disp,
273349cc55cSDimitry Andric                          SDValue &Base) {
274349cc55cSDimitry Andric       return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
275bdd1243dSDimitry Andric                                                 std::nullopt) == PPC::AM_PCRel;
276349cc55cSDimitry Andric     }
277349cc55cSDimitry Andric 
278349cc55cSDimitry Andric     /// SelectPDForm - Returns true if address N can be represented by Prefixed
279349cc55cSDimitry Andric     /// DForm addressing mode (a base register, plus a signed 34-bit immediate.
SelectPDForm(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)280349cc55cSDimitry Andric     bool SelectPDForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
281349cc55cSDimitry Andric       return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
282bdd1243dSDimitry Andric                                                 std::nullopt) ==
283bdd1243dSDimitry Andric              PPC::AM_PrefixDForm;
284349cc55cSDimitry Andric     }
285349cc55cSDimitry Andric 
286fe6060f1SDimitry Andric     /// SelectXForm - Returns true if address N can be represented by the
287fe6060f1SDimitry Andric     /// addressing mode of XForm instructions (an indexed [r+r] operation).
SelectXForm(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)288fe6060f1SDimitry Andric     bool SelectXForm(SDNode *Parent, SDValue N, SDValue &Disp, SDValue &Base) {
289fe6060f1SDimitry Andric       return PPCLowering->SelectOptimalAddrMode(Parent, N, Disp, Base, *CurDAG,
290bdd1243dSDimitry Andric                                                 std::nullopt) == PPC::AM_XForm;
291fe6060f1SDimitry Andric     }
292fe6060f1SDimitry Andric 
293fe6060f1SDimitry Andric     /// SelectForceXForm - Given the specified address, force it to be
294fe6060f1SDimitry Andric     /// represented as an indexed [r+r] operation (an XForm instruction).
SelectForceXForm(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)295fe6060f1SDimitry Andric     bool SelectForceXForm(SDNode *Parent, SDValue N, SDValue &Disp,
296fe6060f1SDimitry Andric                           SDValue &Base) {
297fe6060f1SDimitry Andric       return PPCLowering->SelectForceXFormMode(N, Disp, Base, *CurDAG) ==
298fe6060f1SDimitry Andric              PPC::AM_XForm;
299fe6060f1SDimitry Andric     }
300fe6060f1SDimitry Andric 
3010b57cec5SDimitry Andric     /// SelectAddrIdx - Given the specified address, check to see if it can be
3020b57cec5SDimitry Andric     /// represented as an indexed [r+r] operation.
3030b57cec5SDimitry Andric     /// This is for xform instructions whose associated displacement form is D.
3040b57cec5SDimitry Andric     /// The last parameter \p 0 means associated D form has no requirment for 16
3050b57cec5SDimitry Andric     /// bit signed displacement.
3060b57cec5SDimitry Andric     /// Returns false if it can be represented by [r+imm], which are preferred.
SelectAddrIdx(SDValue N,SDValue & Base,SDValue & Index)3070b57cec5SDimitry Andric     bool SelectAddrIdx(SDValue N, SDValue &Base, SDValue &Index) {
308bdd1243dSDimitry Andric       return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG,
309bdd1243dSDimitry Andric                                               std::nullopt);
3100b57cec5SDimitry Andric     }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric     /// SelectAddrIdx4 - Given the specified address, check to see if it can be
3130b57cec5SDimitry Andric     /// represented as an indexed [r+r] operation.
3140b57cec5SDimitry Andric     /// This is for xform instructions whose associated displacement form is DS.
3150b57cec5SDimitry Andric     /// The last parameter \p 4 means associated DS form 16 bit signed
3160b57cec5SDimitry Andric     /// displacement must be a multiple of 4.
3170b57cec5SDimitry Andric     /// Returns false if it can be represented by [r+imm], which are preferred.
SelectAddrIdxX4(SDValue N,SDValue & Base,SDValue & Index)3180b57cec5SDimitry Andric     bool SelectAddrIdxX4(SDValue N, SDValue &Base, SDValue &Index) {
3195ffd83dbSDimitry Andric       return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG,
3205ffd83dbSDimitry Andric                                               Align(4));
3210b57cec5SDimitry Andric     }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric     /// SelectAddrIdx16 - Given the specified address, check to see if it can be
3240b57cec5SDimitry Andric     /// represented as an indexed [r+r] operation.
3250b57cec5SDimitry Andric     /// This is for xform instructions whose associated displacement form is DQ.
3260b57cec5SDimitry Andric     /// The last parameter \p 16 means associated DQ form 16 bit signed
3270b57cec5SDimitry Andric     /// displacement must be a multiple of 16.
3280b57cec5SDimitry Andric     /// Returns false if it can be represented by [r+imm], which are preferred.
SelectAddrIdxX16(SDValue N,SDValue & Base,SDValue & Index)3290b57cec5SDimitry Andric     bool SelectAddrIdxX16(SDValue N, SDValue &Base, SDValue &Index) {
3305ffd83dbSDimitry Andric       return PPCLowering->SelectAddressRegReg(N, Base, Index, *CurDAG,
3315ffd83dbSDimitry Andric                                               Align(16));
3320b57cec5SDimitry Andric     }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric     /// SelectAddrIdxOnly - Given the specified address, force it to be
3350b57cec5SDimitry Andric     /// represented as an indexed [r+r] operation.
SelectAddrIdxOnly(SDValue N,SDValue & Base,SDValue & Index)3360b57cec5SDimitry Andric     bool SelectAddrIdxOnly(SDValue N, SDValue &Base, SDValue &Index) {
3370b57cec5SDimitry Andric       return PPCLowering->SelectAddressRegRegOnly(N, Base, Index, *CurDAG);
3380b57cec5SDimitry Andric     }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric     /// SelectAddrImm - Returns true if the address N can be represented by
3410b57cec5SDimitry Andric     /// a base register plus a signed 16-bit displacement [r+imm].
3420b57cec5SDimitry Andric     /// The last parameter \p 0 means D form has no requirment for 16 bit signed
3430b57cec5SDimitry Andric     /// displacement.
SelectAddrImm(SDValue N,SDValue & Disp,SDValue & Base)3440b57cec5SDimitry Andric     bool SelectAddrImm(SDValue N, SDValue &Disp,
3450b57cec5SDimitry Andric                        SDValue &Base) {
346bdd1243dSDimitry Andric       return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG,
347bdd1243dSDimitry Andric                                               std::nullopt);
3480b57cec5SDimitry Andric     }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric     /// SelectAddrImmX4 - Returns true if the address N can be represented by
3510b57cec5SDimitry Andric     /// a base register plus a signed 16-bit displacement that is a multiple of
3520b57cec5SDimitry Andric     /// 4 (last parameter). Suitable for use by STD and friends.
SelectAddrImmX4(SDValue N,SDValue & Disp,SDValue & Base)3530b57cec5SDimitry Andric     bool SelectAddrImmX4(SDValue N, SDValue &Disp, SDValue &Base) {
3545ffd83dbSDimitry Andric       return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG, Align(4));
3550b57cec5SDimitry Andric     }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric     /// SelectAddrImmX16 - Returns true if the address N can be represented by
3580b57cec5SDimitry Andric     /// a base register plus a signed 16-bit displacement that is a multiple of
3590b57cec5SDimitry Andric     /// 16(last parameter). Suitable for use by STXV and friends.
SelectAddrImmX16(SDValue N,SDValue & Disp,SDValue & Base)3600b57cec5SDimitry Andric     bool SelectAddrImmX16(SDValue N, SDValue &Disp, SDValue &Base) {
3615ffd83dbSDimitry Andric       return PPCLowering->SelectAddressRegImm(N, Disp, Base, *CurDAG,
3625ffd83dbSDimitry Andric                                               Align(16));
3630b57cec5SDimitry Andric     }
3640b57cec5SDimitry Andric 
365e8d8bef9SDimitry Andric     /// SelectAddrImmX34 - Returns true if the address N can be represented by
366e8d8bef9SDimitry Andric     /// a base register plus a signed 34-bit displacement. Suitable for use by
367e8d8bef9SDimitry Andric     /// PSTXVP and friends.
SelectAddrImmX34(SDValue N,SDValue & Disp,SDValue & Base)368e8d8bef9SDimitry Andric     bool SelectAddrImmX34(SDValue N, SDValue &Disp, SDValue &Base) {
369e8d8bef9SDimitry Andric       return PPCLowering->SelectAddressRegImm34(N, Disp, Base, *CurDAG);
370e8d8bef9SDimitry Andric     }
371e8d8bef9SDimitry Andric 
3720b57cec5SDimitry Andric     // Select an address into a single register.
SelectAddr(SDValue N,SDValue & Base)3730b57cec5SDimitry Andric     bool SelectAddr(SDValue N, SDValue &Base) {
3740b57cec5SDimitry Andric       Base = N;
3750b57cec5SDimitry Andric       return true;
3760b57cec5SDimitry Andric     }
3770b57cec5SDimitry Andric 
SelectAddrPCRel(SDValue N,SDValue & Base)3785ffd83dbSDimitry Andric     bool SelectAddrPCRel(SDValue N, SDValue &Base) {
3795ffd83dbSDimitry Andric       return PPCLowering->SelectAddressPCRel(N, Base);
3805ffd83dbSDimitry Andric     }
3815ffd83dbSDimitry Andric 
3820b57cec5SDimitry Andric     /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
3830b57cec5SDimitry Andric     /// inline asm expressions.  It is always correct to compute the value into
3840b57cec5SDimitry Andric     /// a register.  The case of adding a (possibly relocatable) constant to a
3850b57cec5SDimitry Andric     /// register can be improved, but it is wrong to substitute Reg+Reg for
3860b57cec5SDimitry Andric     /// Reg in an asm, because the load or store opcode would have to change.
SelectInlineAsmMemoryOperand(const SDValue & Op,InlineAsm::ConstraintCode ConstraintID,std::vector<SDValue> & OutOps)3870b57cec5SDimitry Andric     bool SelectInlineAsmMemoryOperand(const SDValue &Op,
3885f757f3fSDimitry Andric                                       InlineAsm::ConstraintCode ConstraintID,
3890b57cec5SDimitry Andric                                       std::vector<SDValue> &OutOps) override {
3900b57cec5SDimitry Andric       switch(ConstraintID) {
3910b57cec5SDimitry Andric       default:
3925f757f3fSDimitry Andric         errs() << "ConstraintID: "
3935f757f3fSDimitry Andric                << InlineAsm::getMemConstraintName(ConstraintID) << "\n";
3940b57cec5SDimitry Andric         llvm_unreachable("Unexpected asm memory constraint");
3955f757f3fSDimitry Andric       case InlineAsm::ConstraintCode::es:
3965f757f3fSDimitry Andric       case InlineAsm::ConstraintCode::m:
3975f757f3fSDimitry Andric       case InlineAsm::ConstraintCode::o:
3985f757f3fSDimitry Andric       case InlineAsm::ConstraintCode::Q:
3995f757f3fSDimitry Andric       case InlineAsm::ConstraintCode::Z:
4005f757f3fSDimitry Andric       case InlineAsm::ConstraintCode::Zy:
4010b57cec5SDimitry Andric         // We need to make sure that this one operand does not end up in r0
4020b57cec5SDimitry Andric         // (because we might end up lowering this as 0(%op)).
4035ffd83dbSDimitry Andric         const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
4040b57cec5SDimitry Andric         const TargetRegisterClass *TRC = TRI->getPointerRegClass(*MF, /*Kind=*/1);
4050b57cec5SDimitry Andric         SDLoc dl(Op);
4060b57cec5SDimitry Andric         SDValue RC = CurDAG->getTargetConstant(TRC->getID(), dl, MVT::i32);
4070b57cec5SDimitry Andric         SDValue NewOp =
4080b57cec5SDimitry Andric           SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
4090b57cec5SDimitry Andric                                          dl, Op.getValueType(),
4100b57cec5SDimitry Andric                                          Op, RC), 0);
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric         OutOps.push_back(NewOp);
4130b57cec5SDimitry Andric         return false;
4140b57cec5SDimitry Andric       }
4150b57cec5SDimitry Andric       return true;
4160b57cec5SDimitry Andric     }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric // Include the pieces autogenerated from the target description.
4190b57cec5SDimitry Andric #include "PPCGenDAGISel.inc"
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric private:
4220b57cec5SDimitry Andric     bool trySETCC(SDNode *N);
423e8d8bef9SDimitry Andric     bool tryFoldSWTestBRCC(SDNode *N);
424bdd1243dSDimitry Andric     bool trySelectLoopCountIntrinsic(SDNode *N);
4255ffd83dbSDimitry Andric     bool tryAsSingleRLDICL(SDNode *N);
4265f757f3fSDimitry Andric     bool tryAsSingleRLDCL(SDNode *N);
4275ffd83dbSDimitry Andric     bool tryAsSingleRLDICR(SDNode *N);
4285ffd83dbSDimitry Andric     bool tryAsSingleRLWINM(SDNode *N);
4295ffd83dbSDimitry Andric     bool tryAsSingleRLWINM8(SDNode *N);
4305ffd83dbSDimitry Andric     bool tryAsSingleRLWIMI(SDNode *N);
4315ffd83dbSDimitry Andric     bool tryAsPairOfRLDICL(SDNode *N);
4325ffd83dbSDimitry Andric     bool tryAsSingleRLDIMI(SDNode *N);
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric     void PeepholePPC64();
4350b57cec5SDimitry Andric     void PeepholePPC64ZExt();
4360b57cec5SDimitry Andric     void PeepholeCROps();
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric     SDValue combineToCMPB(SDNode *N);
4390b57cec5SDimitry Andric     void foldBoolExts(SDValue &Res, SDNode *&N);
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric     bool AllUsersSelectZero(SDNode *N);
4420b57cec5SDimitry Andric     void SwapAllSelectUsers(SDNode *N);
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric     bool isOffsetMultipleOf(SDNode *N, unsigned Val) const;
4450b57cec5SDimitry Andric     void transferMemOperands(SDNode *N, SDNode *Result);
4460b57cec5SDimitry Andric   };
4470b57cec5SDimitry Andric 
448*0fca6ea1SDimitry Andric   class PPCDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
449*0fca6ea1SDimitry Andric   public:
450*0fca6ea1SDimitry Andric     static char ID;
PPCDAGToDAGISelLegacy(PPCTargetMachine & tm,CodeGenOptLevel OptLevel)451*0fca6ea1SDimitry Andric     explicit PPCDAGToDAGISelLegacy(PPCTargetMachine &tm,
452*0fca6ea1SDimitry Andric                                    CodeGenOptLevel OptLevel)
453*0fca6ea1SDimitry Andric         : SelectionDAGISelLegacy(
454*0fca6ea1SDimitry Andric               ID, std::make_unique<PPCDAGToDAGISel>(tm, OptLevel)) {}
455*0fca6ea1SDimitry Andric   };
4560b57cec5SDimitry Andric } // end anonymous namespace
4570b57cec5SDimitry Andric 
458*0fca6ea1SDimitry Andric char PPCDAGToDAGISelLegacy::ID = 0;
459bdd1243dSDimitry Andric 
INITIALIZE_PASS(PPCDAGToDAGISelLegacy,DEBUG_TYPE,PASS_NAME,false,false)460*0fca6ea1SDimitry Andric INITIALIZE_PASS(PPCDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
461bdd1243dSDimitry Andric 
4620b57cec5SDimitry Andric /// getGlobalBaseReg - Output the instructions required to put the
4630b57cec5SDimitry Andric /// base address to use for accessing globals into a register.
4640b57cec5SDimitry Andric ///
4650b57cec5SDimitry Andric SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {
4660b57cec5SDimitry Andric   if (!GlobalBaseReg) {
4675ffd83dbSDimitry Andric     const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
4680b57cec5SDimitry Andric     // Insert the set of GlobalBaseReg into the first MBB of the function
4690b57cec5SDimitry Andric     MachineBasicBlock &FirstMBB = MF->front();
4700b57cec5SDimitry Andric     MachineBasicBlock::iterator MBBI = FirstMBB.begin();
4710b57cec5SDimitry Andric     const Module *M = MF->getFunction().getParent();
4720b57cec5SDimitry Andric     DebugLoc dl;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric     if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) == MVT::i32) {
4755ffd83dbSDimitry Andric       if (Subtarget->isTargetELF()) {
4760b57cec5SDimitry Andric         GlobalBaseReg = PPC::R30;
4775ffd83dbSDimitry Andric         if (!Subtarget->isSecurePlt() &&
4780b57cec5SDimitry Andric             M->getPICLevel() == PICLevel::SmallPIC) {
4790b57cec5SDimitry Andric           BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MoveGOTtoLR));
4800b57cec5SDimitry Andric           BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg);
4810b57cec5SDimitry Andric           MF->getInfo<PPCFunctionInfo>()->setUsesPICBase(true);
4820b57cec5SDimitry Andric         } else {
4830b57cec5SDimitry Andric           BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR));
4840b57cec5SDimitry Andric           BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg);
4858bcb0991SDimitry Andric           Register TempReg = RegInfo->createVirtualRegister(&PPC::GPRCRegClass);
4860b57cec5SDimitry Andric           BuildMI(FirstMBB, MBBI, dl,
4870b57cec5SDimitry Andric                   TII.get(PPC::UpdateGBR), GlobalBaseReg)
4880b57cec5SDimitry Andric                   .addReg(TempReg, RegState::Define).addReg(GlobalBaseReg);
4890b57cec5SDimitry Andric           MF->getInfo<PPCFunctionInfo>()->setUsesPICBase(true);
4900b57cec5SDimitry Andric         }
4910b57cec5SDimitry Andric       } else {
4920b57cec5SDimitry Andric         GlobalBaseReg =
4930b57cec5SDimitry Andric           RegInfo->createVirtualRegister(&PPC::GPRC_and_GPRC_NOR0RegClass);
4940b57cec5SDimitry Andric         BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR));
4950b57cec5SDimitry Andric         BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg);
4960b57cec5SDimitry Andric       }
4970b57cec5SDimitry Andric     } else {
4980b57cec5SDimitry Andric       // We must ensure that this sequence is dominated by the prologue.
4990b57cec5SDimitry Andric       // FIXME: This is a bit of a big hammer since we don't get the benefits
5000b57cec5SDimitry Andric       // of shrink-wrapping whenever we emit this instruction. Considering
5010b57cec5SDimitry Andric       // this is used in any function where we emit a jump table, this may be
5020b57cec5SDimitry Andric       // a significant limitation. We should consider inserting this in the
5030b57cec5SDimitry Andric       // block where it is used and then commoning this sequence up if it
5040b57cec5SDimitry Andric       // appears in multiple places.
5050b57cec5SDimitry Andric       // Note: on ISA 3.0 cores, we can use lnia (addpcis) instead of
5060b57cec5SDimitry Andric       // MovePCtoLR8.
5070b57cec5SDimitry Andric       MF->getInfo<PPCFunctionInfo>()->setShrinkWrapDisabled(true);
5080b57cec5SDimitry Andric       GlobalBaseReg = RegInfo->createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass);
5090b57cec5SDimitry Andric       BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR8));
5100b57cec5SDimitry Andric       BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR8), GlobalBaseReg);
5110b57cec5SDimitry Andric     }
5120b57cec5SDimitry Andric   }
5130b57cec5SDimitry Andric   return CurDAG->getRegister(GlobalBaseReg,
5140b57cec5SDimitry Andric                              PPCLowering->getPointerTy(CurDAG->getDataLayout()))
5150b57cec5SDimitry Andric       .getNode();
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric 
518fe6060f1SDimitry Andric // Check if a SDValue has the toc-data attribute.
hasTocDataAttr(SDValue Val)519*0fca6ea1SDimitry Andric static bool hasTocDataAttr(SDValue Val) {
520fe6060f1SDimitry Andric   GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Val);
521fe6060f1SDimitry Andric   if (!GA)
522fe6060f1SDimitry Andric     return false;
523fe6060f1SDimitry Andric 
524fe6060f1SDimitry Andric   const GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(GA->getGlobal());
525fe6060f1SDimitry Andric   if (!GV)
526fe6060f1SDimitry Andric     return false;
527fe6060f1SDimitry Andric 
528fe6060f1SDimitry Andric   if (!GV->hasAttribute("toc-data"))
529fe6060f1SDimitry Andric     return false;
530fe6060f1SDimitry Andric   return true;
531fe6060f1SDimitry Andric }
532fe6060f1SDimitry Andric 
getCodeModel(const PPCSubtarget & Subtarget,const TargetMachine & TM,const SDNode * Node)533*0fca6ea1SDimitry Andric static CodeModel::Model getCodeModel(const PPCSubtarget &Subtarget,
534*0fca6ea1SDimitry Andric                                      const TargetMachine &TM,
535*0fca6ea1SDimitry Andric                                      const SDNode *Node) {
536*0fca6ea1SDimitry Andric   // If there isn't an attribute to override the module code model
537*0fca6ea1SDimitry Andric   // this will be the effective code model.
538*0fca6ea1SDimitry Andric   CodeModel::Model ModuleModel = TM.getCodeModel();
539*0fca6ea1SDimitry Andric 
540*0fca6ea1SDimitry Andric   GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Node->getOperand(0));
541*0fca6ea1SDimitry Andric   if (!GA)
542*0fca6ea1SDimitry Andric     return ModuleModel;
543*0fca6ea1SDimitry Andric 
544*0fca6ea1SDimitry Andric   const GlobalValue *GV = GA->getGlobal();
545*0fca6ea1SDimitry Andric   if (!GV)
546*0fca6ea1SDimitry Andric     return ModuleModel;
547*0fca6ea1SDimitry Andric 
548*0fca6ea1SDimitry Andric   return Subtarget.getCodeModel(TM, GV);
549*0fca6ea1SDimitry Andric }
550*0fca6ea1SDimitry Andric 
5510b57cec5SDimitry Andric /// isInt32Immediate - This method tests to see if the node is a 32-bit constant
5520b57cec5SDimitry Andric /// operand. If so Imm will receive the 32-bit value.
isInt32Immediate(SDNode * N,unsigned & Imm)5530b57cec5SDimitry Andric static bool isInt32Immediate(SDNode *N, unsigned &Imm) {
5540b57cec5SDimitry Andric   if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) {
5551db9f3b2SDimitry Andric     Imm = N->getAsZExtVal();
5560b57cec5SDimitry Andric     return true;
5570b57cec5SDimitry Andric   }
5580b57cec5SDimitry Andric   return false;
5590b57cec5SDimitry Andric }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric /// isInt64Immediate - This method tests to see if the node is a 64-bit constant
5620b57cec5SDimitry Andric /// operand.  If so Imm will receive the 64-bit value.
isInt64Immediate(SDNode * N,uint64_t & Imm)5630b57cec5SDimitry Andric static bool isInt64Immediate(SDNode *N, uint64_t &Imm) {
5640b57cec5SDimitry Andric   if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i64) {
5651db9f3b2SDimitry Andric     Imm = N->getAsZExtVal();
5660b57cec5SDimitry Andric     return true;
5670b57cec5SDimitry Andric   }
5680b57cec5SDimitry Andric   return false;
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric // isInt32Immediate - This method tests to see if a constant operand.
5720b57cec5SDimitry Andric // If so Imm will receive the 32 bit value.
isInt32Immediate(SDValue N,unsigned & Imm)5730b57cec5SDimitry Andric static bool isInt32Immediate(SDValue N, unsigned &Imm) {
5740b57cec5SDimitry Andric   return isInt32Immediate(N.getNode(), Imm);
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric /// isInt64Immediate - This method tests to see if the value is a 64-bit
5780b57cec5SDimitry Andric /// constant operand. If so Imm will receive the 64-bit value.
isInt64Immediate(SDValue N,uint64_t & Imm)5790b57cec5SDimitry Andric static bool isInt64Immediate(SDValue N, uint64_t &Imm) {
5800b57cec5SDimitry Andric   return isInt64Immediate(N.getNode(), Imm);
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
getBranchHint(unsigned PCC,const FunctionLoweringInfo & FuncInfo,const SDValue & DestMBB)583480093f4SDimitry Andric static unsigned getBranchHint(unsigned PCC,
584480093f4SDimitry Andric                               const FunctionLoweringInfo &FuncInfo,
5850b57cec5SDimitry Andric                               const SDValue &DestMBB) {
5860b57cec5SDimitry Andric   assert(isa<BasicBlockSDNode>(DestMBB));
5870b57cec5SDimitry Andric 
588480093f4SDimitry Andric   if (!FuncInfo.BPI) return PPC::BR_NO_HINT;
5890b57cec5SDimitry Andric 
590480093f4SDimitry Andric   const BasicBlock *BB = FuncInfo.MBB->getBasicBlock();
5910b57cec5SDimitry Andric   const Instruction *BBTerm = BB->getTerminator();
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   if (BBTerm->getNumSuccessors() != 2) return PPC::BR_NO_HINT;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   const BasicBlock *TBB = BBTerm->getSuccessor(0);
5960b57cec5SDimitry Andric   const BasicBlock *FBB = BBTerm->getSuccessor(1);
5970b57cec5SDimitry Andric 
598480093f4SDimitry Andric   auto TProb = FuncInfo.BPI->getEdgeProbability(BB, TBB);
599480093f4SDimitry Andric   auto FProb = FuncInfo.BPI->getEdgeProbability(BB, FBB);
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   // We only want to handle cases which are easy to predict at static time, e.g.
6020b57cec5SDimitry Andric   // C++ throw statement, that is very likely not taken, or calling never
6030b57cec5SDimitry Andric   // returned function, e.g. stdlib exit(). So we set Threshold to filter
6040b57cec5SDimitry Andric   // unwanted cases.
6050b57cec5SDimitry Andric   //
6060b57cec5SDimitry Andric   // Below is LLVM branch weight table, we only want to handle case 1, 2
6070b57cec5SDimitry Andric   //
6080b57cec5SDimitry Andric   // Case                  Taken:Nontaken  Example
6090b57cec5SDimitry Andric   // 1. Unreachable        1048575:1       C++ throw, stdlib exit(),
6100b57cec5SDimitry Andric   // 2. Invoke-terminating 1:1048575
6110b57cec5SDimitry Andric   // 3. Coldblock          4:64            __builtin_expect
6120b57cec5SDimitry Andric   // 4. Loop Branch        124:4           For loop
6130b57cec5SDimitry Andric   // 5. PH/ZH/FPH          20:12
6140b57cec5SDimitry Andric   const uint32_t Threshold = 10000;
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   if (std::max(TProb, FProb) / Threshold < std::min(TProb, FProb))
6170b57cec5SDimitry Andric     return PPC::BR_NO_HINT;
6180b57cec5SDimitry Andric 
619480093f4SDimitry Andric   LLVM_DEBUG(dbgs() << "Use branch hint for '" << FuncInfo.Fn->getName()
6200b57cec5SDimitry Andric                     << "::" << BB->getName() << "'\n"
6210b57cec5SDimitry Andric                     << " -> " << TBB->getName() << ": " << TProb << "\n"
6220b57cec5SDimitry Andric                     << " -> " << FBB->getName() << ": " << FProb << "\n");
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric   const BasicBlockSDNode *BBDN = cast<BasicBlockSDNode>(DestMBB);
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   // If Dest BasicBlock is False-BasicBlock (FBB), swap branch probabilities,
6270b57cec5SDimitry Andric   // because we want 'TProb' stands for 'branch probability' to Dest BasicBlock
6280b57cec5SDimitry Andric   if (BBDN->getBasicBlock()->getBasicBlock() != TBB)
6290b57cec5SDimitry Andric     std::swap(TProb, FProb);
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric   return (TProb > FProb) ? PPC::BR_TAKEN_HINT : PPC::BR_NONTAKEN_HINT;
6320b57cec5SDimitry Andric }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric // isOpcWithIntImmediate - This method tests to see if the node is a specific
6350b57cec5SDimitry Andric // opcode and that it has a immediate integer right operand.
6360b57cec5SDimitry Andric // If so Imm will receive the 32 bit value.
isOpcWithIntImmediate(SDNode * N,unsigned Opc,unsigned & Imm)6370b57cec5SDimitry Andric static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) {
6380b57cec5SDimitry Andric   return N->getOpcode() == Opc
6390b57cec5SDimitry Andric          && isInt32Immediate(N->getOperand(1).getNode(), Imm);
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
selectFrameIndex(SDNode * SN,SDNode * N,uint64_t Offset)64281ad6265SDimitry Andric void PPCDAGToDAGISel::selectFrameIndex(SDNode *SN, SDNode *N, uint64_t Offset) {
6430b57cec5SDimitry Andric   SDLoc dl(SN);
6440b57cec5SDimitry Andric   int FI = cast<FrameIndexSDNode>(N)->getIndex();
6450b57cec5SDimitry Andric   SDValue TFI = CurDAG->getTargetFrameIndex(FI, N->getValueType(0));
6460b57cec5SDimitry Andric   unsigned Opc = N->getValueType(0) == MVT::i32 ? PPC::ADDI : PPC::ADDI8;
6470b57cec5SDimitry Andric   if (SN->hasOneUse())
6480b57cec5SDimitry Andric     CurDAG->SelectNodeTo(SN, Opc, N->getValueType(0), TFI,
6490b57cec5SDimitry Andric                          getSmallIPtrImm(Offset, dl));
6500b57cec5SDimitry Andric   else
6510b57cec5SDimitry Andric     ReplaceNode(SN, CurDAG->getMachineNode(Opc, dl, N->getValueType(0), TFI,
6520b57cec5SDimitry Andric                                            getSmallIPtrImm(Offset, dl)));
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
isRotateAndMask(SDNode * N,unsigned Mask,bool isShiftMask,unsigned & SH,unsigned & MB,unsigned & ME)6550b57cec5SDimitry Andric bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask,
6560b57cec5SDimitry Andric                                       bool isShiftMask, unsigned &SH,
6570b57cec5SDimitry Andric                                       unsigned &MB, unsigned &ME) {
6580b57cec5SDimitry Andric   // Don't even go down this path for i64, since different logic will be
6590b57cec5SDimitry Andric   // necessary for rldicl/rldicr/rldimi.
6600b57cec5SDimitry Andric   if (N->getValueType(0) != MVT::i32)
6610b57cec5SDimitry Andric     return false;
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   unsigned Shift  = 32;
6640b57cec5SDimitry Andric   unsigned Indeterminant = ~0;  // bit mask marking indeterminant results
6650b57cec5SDimitry Andric   unsigned Opcode = N->getOpcode();
6660b57cec5SDimitry Andric   if (N->getNumOperands() != 2 ||
6670b57cec5SDimitry Andric       !isInt32Immediate(N->getOperand(1).getNode(), Shift) || (Shift > 31))
6680b57cec5SDimitry Andric     return false;
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   if (Opcode == ISD::SHL) {
6710b57cec5SDimitry Andric     // apply shift left to mask if it comes first
6720b57cec5SDimitry Andric     if (isShiftMask) Mask = Mask << Shift;
6730b57cec5SDimitry Andric     // determine which bits are made indeterminant by shift
6740b57cec5SDimitry Andric     Indeterminant = ~(0xFFFFFFFFu << Shift);
6750b57cec5SDimitry Andric   } else if (Opcode == ISD::SRL) {
6760b57cec5SDimitry Andric     // apply shift right to mask if it comes first
6770b57cec5SDimitry Andric     if (isShiftMask) Mask = Mask >> Shift;
6780b57cec5SDimitry Andric     // determine which bits are made indeterminant by shift
6790b57cec5SDimitry Andric     Indeterminant = ~(0xFFFFFFFFu >> Shift);
6800b57cec5SDimitry Andric     // adjust for the left rotate
6810b57cec5SDimitry Andric     Shift = 32 - Shift;
6820b57cec5SDimitry Andric   } else if (Opcode == ISD::ROTL) {
6830b57cec5SDimitry Andric     Indeterminant = 0;
6840b57cec5SDimitry Andric   } else {
6850b57cec5SDimitry Andric     return false;
6860b57cec5SDimitry Andric   }
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric   // if the mask doesn't intersect any Indeterminant bits
6890b57cec5SDimitry Andric   if (Mask && !(Mask & Indeterminant)) {
6900b57cec5SDimitry Andric     SH = Shift & 31;
6910b57cec5SDimitry Andric     // make sure the mask is still a mask (wrap arounds may not be)
6920b57cec5SDimitry Andric     return isRunOfOnes(Mask, MB, ME);
6930b57cec5SDimitry Andric   }
6940b57cec5SDimitry Andric   return false;
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
69706c3fb27SDimitry Andric // isThreadPointerAcquisitionNode - Check if the operands of an ADD_TLS
69806c3fb27SDimitry Andric // instruction use the thread pointer.
isThreadPointerAcquisitionNode(SDValue Base,SelectionDAG * CurDAG)69906c3fb27SDimitry Andric static bool isThreadPointerAcquisitionNode(SDValue Base, SelectionDAG *CurDAG) {
70006c3fb27SDimitry Andric   assert(
70106c3fb27SDimitry Andric       Base.getOpcode() == PPCISD::ADD_TLS &&
70206c3fb27SDimitry Andric       "Only expecting the ADD_TLS instruction to acquire the thread pointer!");
70306c3fb27SDimitry Andric   const PPCSubtarget &Subtarget =
70406c3fb27SDimitry Andric       CurDAG->getMachineFunction().getSubtarget<PPCSubtarget>();
70506c3fb27SDimitry Andric   SDValue ADDTLSOp1 = Base.getOperand(0);
70606c3fb27SDimitry Andric   unsigned ADDTLSOp1Opcode = ADDTLSOp1.getOpcode();
70706c3fb27SDimitry Andric 
70806c3fb27SDimitry Andric   // Account for when ADD_TLS is used for the initial-exec TLS model on Linux.
70906c3fb27SDimitry Andric   //
71006c3fb27SDimitry Andric   // Although ADD_TLS does not explicitly use the thread pointer
71106c3fb27SDimitry Andric   // register when LD_GOT_TPREL_L is one of it's operands, the LD_GOT_TPREL_L
71206c3fb27SDimitry Andric   // instruction will have a relocation specifier, @got@tprel, that is used to
71306c3fb27SDimitry Andric   // generate a GOT entry. The linker replaces this entry with an offset for a
71406c3fb27SDimitry Andric   // for a thread local variable, which will be relative to the thread pointer.
71506c3fb27SDimitry Andric   if (ADDTLSOp1Opcode == PPCISD::LD_GOT_TPREL_L)
71606c3fb27SDimitry Andric     return true;
71706c3fb27SDimitry Andric   // When using PC-Relative instructions for initial-exec, a MAT_PCREL_ADDR
71806c3fb27SDimitry Andric   // node is produced instead to represent the aforementioned situation.
71906c3fb27SDimitry Andric   LoadSDNode *LD = dyn_cast<LoadSDNode>(ADDTLSOp1);
72006c3fb27SDimitry Andric   if (LD && LD->getBasePtr().getOpcode() == PPCISD::MAT_PCREL_ADDR)
72106c3fb27SDimitry Andric     return true;
72206c3fb27SDimitry Andric 
72306c3fb27SDimitry Andric   // A GET_TPOINTER PPCISD node (only produced on AIX 32-bit mode) as an operand
72406c3fb27SDimitry Andric   // to ADD_TLS represents a call to .__get_tpointer to get the thread pointer,
72506c3fb27SDimitry Andric   // later returning it into R3.
72606c3fb27SDimitry Andric   if (ADDTLSOp1Opcode == PPCISD::GET_TPOINTER)
72706c3fb27SDimitry Andric     return true;
72806c3fb27SDimitry Andric 
72906c3fb27SDimitry Andric   // The ADD_TLS note is explicitly acquiring the thread pointer (X13/R13).
73006c3fb27SDimitry Andric   RegisterSDNode *AddFirstOpReg =
73106c3fb27SDimitry Andric       dyn_cast_or_null<RegisterSDNode>(ADDTLSOp1.getNode());
73206c3fb27SDimitry Andric   if (AddFirstOpReg &&
73306c3fb27SDimitry Andric       AddFirstOpReg->getReg() == Subtarget.getThreadPointerRegister())
73406c3fb27SDimitry Andric       return true;
73506c3fb27SDimitry Andric 
73606c3fb27SDimitry Andric   return false;
73706c3fb27SDimitry Andric }
73806c3fb27SDimitry Andric 
73906c3fb27SDimitry Andric // canOptimizeTLSDFormToXForm - Optimize TLS accesses when an ADD_TLS
74006c3fb27SDimitry Andric // instruction is present. An ADD_TLS instruction, followed by a D-Form memory
74106c3fb27SDimitry Andric // operation, can be optimized to use an X-Form load or store, allowing the
74206c3fb27SDimitry Andric // ADD_TLS node to be removed completely.
canOptimizeTLSDFormToXForm(SelectionDAG * CurDAG,SDValue Base)74306c3fb27SDimitry Andric static bool canOptimizeTLSDFormToXForm(SelectionDAG *CurDAG, SDValue Base) {
74406c3fb27SDimitry Andric 
74506c3fb27SDimitry Andric   // Do not do this transformation at -O0.
7465f757f3fSDimitry Andric   if (CurDAG->getTarget().getOptLevel() == CodeGenOptLevel::None)
74706c3fb27SDimitry Andric       return false;
74806c3fb27SDimitry Andric 
74906c3fb27SDimitry Andric   // In order to perform this optimization inside tryTLSXForm[Load|Store],
75006c3fb27SDimitry Andric   // Base is expected to be an ADD_TLS node.
7510b57cec5SDimitry Andric   if (Base.getOpcode() != PPCISD::ADD_TLS)
7520b57cec5SDimitry Andric     return false;
75306c3fb27SDimitry Andric   for (auto *ADDTLSUse : Base.getNode()->uses()) {
75406c3fb27SDimitry Andric     // The optimization to convert the D-Form load/store into its X-Form
75506c3fb27SDimitry Andric     // counterpart should only occur if the source value offset of the load/
75606c3fb27SDimitry Andric     // store is 0. This also means that The offset should always be undefined.
75706c3fb27SDimitry Andric     if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ADDTLSUse)) {
75806c3fb27SDimitry Andric       if (LD->getSrcValueOffset() != 0 || !LD->getOffset().isUndef())
7590b57cec5SDimitry Andric         return false;
76006c3fb27SDimitry Andric     } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(ADDTLSUse)) {
76106c3fb27SDimitry Andric       if (ST->getSrcValueOffset() != 0 || !ST->getOffset().isUndef())
76206c3fb27SDimitry Andric         return false;
76306c3fb27SDimitry Andric     } else // Don't optimize if there are ADD_TLS users that aren't load/stores.
76406c3fb27SDimitry Andric       return false;
76506c3fb27SDimitry Andric   }
76606c3fb27SDimitry Andric 
767e8d8bef9SDimitry Andric   if (Base.getOperand(1).getOpcode() == PPCISD::TLS_LOCAL_EXEC_MAT_ADDR)
768e8d8bef9SDimitry Andric     return false;
7690b57cec5SDimitry Andric 
77006c3fb27SDimitry Andric   // Does the ADD_TLS node of the load/store use the thread pointer?
77106c3fb27SDimitry Andric   // If the thread pointer is not used as one of the operands of ADD_TLS,
77206c3fb27SDimitry Andric   // then this optimization is not valid.
77306c3fb27SDimitry Andric   return isThreadPointerAcquisitionNode(Base, CurDAG);
77406c3fb27SDimitry Andric }
77506c3fb27SDimitry Andric 
tryTLSXFormStore(StoreSDNode * ST)77606c3fb27SDimitry Andric bool PPCDAGToDAGISel::tryTLSXFormStore(StoreSDNode *ST) {
77706c3fb27SDimitry Andric   SDValue Base = ST->getBasePtr();
77806c3fb27SDimitry Andric   if (!canOptimizeTLSDFormToXForm(CurDAG, Base))
77906c3fb27SDimitry Andric     return false;
78006c3fb27SDimitry Andric 
7810b57cec5SDimitry Andric   SDLoc dl(ST);
7820b57cec5SDimitry Andric   EVT MemVT = ST->getMemoryVT();
7830b57cec5SDimitry Andric   EVT RegVT = ST->getValue().getValueType();
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   unsigned Opcode;
7860b57cec5SDimitry Andric   switch (MemVT.getSimpleVT().SimpleTy) {
7870b57cec5SDimitry Andric     default:
7880b57cec5SDimitry Andric       return false;
7890b57cec5SDimitry Andric     case MVT::i8: {
7900b57cec5SDimitry Andric       Opcode = (RegVT == MVT::i32) ? PPC::STBXTLS_32 : PPC::STBXTLS;
7910b57cec5SDimitry Andric       break;
7920b57cec5SDimitry Andric     }
7930b57cec5SDimitry Andric     case MVT::i16: {
7940b57cec5SDimitry Andric       Opcode = (RegVT == MVT::i32) ? PPC::STHXTLS_32 : PPC::STHXTLS;
7950b57cec5SDimitry Andric       break;
7960b57cec5SDimitry Andric     }
7970b57cec5SDimitry Andric     case MVT::i32: {
7980b57cec5SDimitry Andric       Opcode = (RegVT == MVT::i32) ? PPC::STWXTLS_32 : PPC::STWXTLS;
7990b57cec5SDimitry Andric       break;
8000b57cec5SDimitry Andric     }
8010b57cec5SDimitry Andric     case MVT::i64: {
8020b57cec5SDimitry Andric       Opcode = PPC::STDXTLS;
8030b57cec5SDimitry Andric       break;
8040b57cec5SDimitry Andric     }
80506c3fb27SDimitry Andric     case MVT::f32: {
80606c3fb27SDimitry Andric       Opcode = PPC::STFSXTLS;
80706c3fb27SDimitry Andric       break;
80806c3fb27SDimitry Andric     }
80906c3fb27SDimitry Andric     case MVT::f64: {
81006c3fb27SDimitry Andric       Opcode = PPC::STFDXTLS;
81106c3fb27SDimitry Andric       break;
81206c3fb27SDimitry Andric     }
8130b57cec5SDimitry Andric   }
8140b57cec5SDimitry Andric   SDValue Chain = ST->getChain();
8150b57cec5SDimitry Andric   SDVTList VTs = ST->getVTList();
8160b57cec5SDimitry Andric   SDValue Ops[] = {ST->getValue(), Base.getOperand(0), Base.getOperand(1),
8170b57cec5SDimitry Andric                    Chain};
8180b57cec5SDimitry Andric   SDNode *MN = CurDAG->getMachineNode(Opcode, dl, VTs, Ops);
8190b57cec5SDimitry Andric   transferMemOperands(ST, MN);
8200b57cec5SDimitry Andric   ReplaceNode(ST, MN);
8210b57cec5SDimitry Andric   return true;
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric 
tryTLSXFormLoad(LoadSDNode * LD)8240b57cec5SDimitry Andric bool PPCDAGToDAGISel::tryTLSXFormLoad(LoadSDNode *LD) {
8250b57cec5SDimitry Andric   SDValue Base = LD->getBasePtr();
82606c3fb27SDimitry Andric   if (!canOptimizeTLSDFormToXForm(CurDAG, Base))
827e8d8bef9SDimitry Andric     return false;
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric   SDLoc dl(LD);
8300b57cec5SDimitry Andric   EVT MemVT = LD->getMemoryVT();
8310b57cec5SDimitry Andric   EVT RegVT = LD->getValueType(0);
83206c3fb27SDimitry Andric   bool isSExt = LD->getExtensionType() == ISD::SEXTLOAD;
8330b57cec5SDimitry Andric   unsigned Opcode;
8340b57cec5SDimitry Andric   switch (MemVT.getSimpleVT().SimpleTy) {
8350b57cec5SDimitry Andric     default:
8360b57cec5SDimitry Andric       return false;
8370b57cec5SDimitry Andric     case MVT::i8: {
8380b57cec5SDimitry Andric       Opcode = (RegVT == MVT::i32) ? PPC::LBZXTLS_32 : PPC::LBZXTLS;
8390b57cec5SDimitry Andric       break;
8400b57cec5SDimitry Andric     }
8410b57cec5SDimitry Andric     case MVT::i16: {
84206c3fb27SDimitry Andric       if (RegVT == MVT::i32)
84306c3fb27SDimitry Andric         Opcode = isSExt ? PPC::LHAXTLS_32 : PPC::LHZXTLS_32;
84406c3fb27SDimitry Andric       else
84506c3fb27SDimitry Andric         Opcode = isSExt ? PPC::LHAXTLS : PPC::LHZXTLS;
8460b57cec5SDimitry Andric       break;
8470b57cec5SDimitry Andric     }
8480b57cec5SDimitry Andric     case MVT::i32: {
84906c3fb27SDimitry Andric       if (RegVT == MVT::i32)
85006c3fb27SDimitry Andric         Opcode = isSExt ? PPC::LWAXTLS_32 : PPC::LWZXTLS_32;
85106c3fb27SDimitry Andric       else
85206c3fb27SDimitry Andric         Opcode = isSExt ? PPC::LWAXTLS : PPC::LWZXTLS;
8530b57cec5SDimitry Andric       break;
8540b57cec5SDimitry Andric     }
8550b57cec5SDimitry Andric     case MVT::i64: {
8560b57cec5SDimitry Andric       Opcode = PPC::LDXTLS;
8570b57cec5SDimitry Andric       break;
8580b57cec5SDimitry Andric     }
85906c3fb27SDimitry Andric     case MVT::f32: {
86006c3fb27SDimitry Andric       Opcode = PPC::LFSXTLS;
86106c3fb27SDimitry Andric       break;
86206c3fb27SDimitry Andric     }
86306c3fb27SDimitry Andric     case MVT::f64: {
86406c3fb27SDimitry Andric       Opcode = PPC::LFDXTLS;
86506c3fb27SDimitry Andric       break;
86606c3fb27SDimitry Andric     }
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric   SDValue Chain = LD->getChain();
8690b57cec5SDimitry Andric   SDVTList VTs = LD->getVTList();
8700b57cec5SDimitry Andric   SDValue Ops[] = {Base.getOperand(0), Base.getOperand(1), Chain};
8710b57cec5SDimitry Andric   SDNode *MN = CurDAG->getMachineNode(Opcode, dl, VTs, Ops);
8720b57cec5SDimitry Andric   transferMemOperands(LD, MN);
8730b57cec5SDimitry Andric   ReplaceNode(LD, MN);
8740b57cec5SDimitry Andric   return true;
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric /// Turn an or of two masked values into the rotate left word immediate then
8780b57cec5SDimitry Andric /// mask insert (rlwimi) instruction.
tryBitfieldInsert(SDNode * N)8790b57cec5SDimitry Andric bool PPCDAGToDAGISel::tryBitfieldInsert(SDNode *N) {
8800b57cec5SDimitry Andric   SDValue Op0 = N->getOperand(0);
8810b57cec5SDimitry Andric   SDValue Op1 = N->getOperand(1);
8820b57cec5SDimitry Andric   SDLoc dl(N);
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric   KnownBits LKnown = CurDAG->computeKnownBits(Op0);
8850b57cec5SDimitry Andric   KnownBits RKnown = CurDAG->computeKnownBits(Op1);
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   unsigned TargetMask = LKnown.Zero.getZExtValue();
8880b57cec5SDimitry Andric   unsigned InsertMask = RKnown.Zero.getZExtValue();
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric   if ((TargetMask | InsertMask) == 0xFFFFFFFF) {
8910b57cec5SDimitry Andric     unsigned Op0Opc = Op0.getOpcode();
8920b57cec5SDimitry Andric     unsigned Op1Opc = Op1.getOpcode();
8930b57cec5SDimitry Andric     unsigned Value, SH = 0;
8940b57cec5SDimitry Andric     TargetMask = ~TargetMask;
8950b57cec5SDimitry Andric     InsertMask = ~InsertMask;
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric     // If the LHS has a foldable shift and the RHS does not, then swap it to the
8980b57cec5SDimitry Andric     // RHS so that we can fold the shift into the insert.
8990b57cec5SDimitry Andric     if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) {
9000b57cec5SDimitry Andric       if (Op0.getOperand(0).getOpcode() == ISD::SHL ||
9010b57cec5SDimitry Andric           Op0.getOperand(0).getOpcode() == ISD::SRL) {
9020b57cec5SDimitry Andric         if (Op1.getOperand(0).getOpcode() != ISD::SHL &&
9030b57cec5SDimitry Andric             Op1.getOperand(0).getOpcode() != ISD::SRL) {
9040b57cec5SDimitry Andric           std::swap(Op0, Op1);
9050b57cec5SDimitry Andric           std::swap(Op0Opc, Op1Opc);
9060b57cec5SDimitry Andric           std::swap(TargetMask, InsertMask);
9070b57cec5SDimitry Andric         }
9080b57cec5SDimitry Andric       }
9090b57cec5SDimitry Andric     } else if (Op0Opc == ISD::SHL || Op0Opc == ISD::SRL) {
9100b57cec5SDimitry Andric       if (Op1Opc == ISD::AND && Op1.getOperand(0).getOpcode() != ISD::SHL &&
9110b57cec5SDimitry Andric           Op1.getOperand(0).getOpcode() != ISD::SRL) {
9120b57cec5SDimitry Andric         std::swap(Op0, Op1);
9130b57cec5SDimitry Andric         std::swap(Op0Opc, Op1Opc);
9140b57cec5SDimitry Andric         std::swap(TargetMask, InsertMask);
9150b57cec5SDimitry Andric       }
9160b57cec5SDimitry Andric     }
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric     unsigned MB, ME;
9190b57cec5SDimitry Andric     if (isRunOfOnes(InsertMask, MB, ME)) {
9200b57cec5SDimitry Andric       if ((Op1Opc == ISD::SHL || Op1Opc == ISD::SRL) &&
9210b57cec5SDimitry Andric           isInt32Immediate(Op1.getOperand(1), Value)) {
9220b57cec5SDimitry Andric         Op1 = Op1.getOperand(0);
9230b57cec5SDimitry Andric         SH  = (Op1Opc == ISD::SHL) ? Value : 32 - Value;
9240b57cec5SDimitry Andric       }
9250b57cec5SDimitry Andric       if (Op1Opc == ISD::AND) {
9260b57cec5SDimitry Andric        // The AND mask might not be a constant, and we need to make sure that
9270b57cec5SDimitry Andric        // if we're going to fold the masking with the insert, all bits not
9280b57cec5SDimitry Andric        // know to be zero in the mask are known to be one.
9290b57cec5SDimitry Andric         KnownBits MKnown = CurDAG->computeKnownBits(Op1.getOperand(1));
9300b57cec5SDimitry Andric         bool CanFoldMask = InsertMask == MKnown.One.getZExtValue();
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric         unsigned SHOpc = Op1.getOperand(0).getOpcode();
9330b57cec5SDimitry Andric         if ((SHOpc == ISD::SHL || SHOpc == ISD::SRL) && CanFoldMask &&
9340b57cec5SDimitry Andric             isInt32Immediate(Op1.getOperand(0).getOperand(1), Value)) {
9350b57cec5SDimitry Andric           // Note that Value must be in range here (less than 32) because
9360b57cec5SDimitry Andric           // otherwise there would not be any bits set in InsertMask.
9370b57cec5SDimitry Andric           Op1 = Op1.getOperand(0).getOperand(0);
9380b57cec5SDimitry Andric           SH  = (SHOpc == ISD::SHL) ? Value : 32 - Value;
9390b57cec5SDimitry Andric         }
9400b57cec5SDimitry Andric       }
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric       SH &= 31;
9430b57cec5SDimitry Andric       SDValue Ops[] = { Op0, Op1, getI32Imm(SH, dl), getI32Imm(MB, dl),
9440b57cec5SDimitry Andric                           getI32Imm(ME, dl) };
9450b57cec5SDimitry Andric       ReplaceNode(N, CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops));
9460b57cec5SDimitry Andric       return true;
9470b57cec5SDimitry Andric     }
9480b57cec5SDimitry Andric   }
9490b57cec5SDimitry Andric   return false;
9500b57cec5SDimitry Andric }
9510b57cec5SDimitry Andric 
allUsesTruncate(SelectionDAG * CurDAG,SDNode * N)9520b57cec5SDimitry Andric static unsigned allUsesTruncate(SelectionDAG *CurDAG, SDNode *N) {
9530b57cec5SDimitry Andric   unsigned MaxTruncation = 0;
9540b57cec5SDimitry Andric   // Cannot use range-based for loop here as we need the actual use (i.e. we
9550b57cec5SDimitry Andric   // need the operand number corresponding to the use). A range-based for
9560b57cec5SDimitry Andric   // will unbox the use and provide an SDNode*.
9570b57cec5SDimitry Andric   for (SDNode::use_iterator Use = N->use_begin(), UseEnd = N->use_end();
9580b57cec5SDimitry Andric        Use != UseEnd; ++Use) {
9590b57cec5SDimitry Andric     unsigned Opc =
9600b57cec5SDimitry Andric       Use->isMachineOpcode() ? Use->getMachineOpcode() : Use->getOpcode();
9610b57cec5SDimitry Andric     switch (Opc) {
9620b57cec5SDimitry Andric     default: return 0;
9630b57cec5SDimitry Andric     case ISD::TRUNCATE:
9640b57cec5SDimitry Andric       if (Use->isMachineOpcode())
9650b57cec5SDimitry Andric         return 0;
9660b57cec5SDimitry Andric       MaxTruncation =
967480093f4SDimitry Andric         std::max(MaxTruncation, (unsigned)Use->getValueType(0).getSizeInBits());
9680b57cec5SDimitry Andric       continue;
9690b57cec5SDimitry Andric     case ISD::STORE: {
9700b57cec5SDimitry Andric       if (Use->isMachineOpcode())
9710b57cec5SDimitry Andric         return 0;
9720b57cec5SDimitry Andric       StoreSDNode *STN = cast<StoreSDNode>(*Use);
9730b57cec5SDimitry Andric       unsigned MemVTSize = STN->getMemoryVT().getSizeInBits();
9740b57cec5SDimitry Andric       if (MemVTSize == 64 || Use.getOperandNo() != 0)
9750b57cec5SDimitry Andric         return 0;
9760b57cec5SDimitry Andric       MaxTruncation = std::max(MaxTruncation, MemVTSize);
9770b57cec5SDimitry Andric       continue;
9780b57cec5SDimitry Andric     }
9790b57cec5SDimitry Andric     case PPC::STW8:
9800b57cec5SDimitry Andric     case PPC::STWX8:
9810b57cec5SDimitry Andric     case PPC::STWU8:
9820b57cec5SDimitry Andric     case PPC::STWUX8:
9830b57cec5SDimitry Andric       if (Use.getOperandNo() != 0)
9840b57cec5SDimitry Andric         return 0;
9850b57cec5SDimitry Andric       MaxTruncation = std::max(MaxTruncation, 32u);
9860b57cec5SDimitry Andric       continue;
9870b57cec5SDimitry Andric     case PPC::STH8:
9880b57cec5SDimitry Andric     case PPC::STHX8:
9890b57cec5SDimitry Andric     case PPC::STHU8:
9900b57cec5SDimitry Andric     case PPC::STHUX8:
9910b57cec5SDimitry Andric       if (Use.getOperandNo() != 0)
9920b57cec5SDimitry Andric         return 0;
9930b57cec5SDimitry Andric       MaxTruncation = std::max(MaxTruncation, 16u);
9940b57cec5SDimitry Andric       continue;
9950b57cec5SDimitry Andric     case PPC::STB8:
9960b57cec5SDimitry Andric     case PPC::STBX8:
9970b57cec5SDimitry Andric     case PPC::STBU8:
9980b57cec5SDimitry Andric     case PPC::STBUX8:
9990b57cec5SDimitry Andric       if (Use.getOperandNo() != 0)
10000b57cec5SDimitry Andric         return 0;
10010b57cec5SDimitry Andric       MaxTruncation = std::max(MaxTruncation, 8u);
10020b57cec5SDimitry Andric       continue;
10030b57cec5SDimitry Andric     }
10040b57cec5SDimitry Andric   }
10050b57cec5SDimitry Andric   return MaxTruncation;
10060b57cec5SDimitry Andric }
10070b57cec5SDimitry Andric 
1008e8d8bef9SDimitry Andric // For any 32 < Num < 64, check if the Imm contains at least Num consecutive
1009e8d8bef9SDimitry Andric // zeros and return the number of bits by the left of these consecutive zeros.
findContiguousZerosAtLeast(uint64_t Imm,unsigned Num)1010e8d8bef9SDimitry Andric static int findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) {
101106c3fb27SDimitry Andric   unsigned HiTZ = llvm::countr_zero<uint32_t>(Hi_32(Imm));
101206c3fb27SDimitry Andric   unsigned LoLZ = llvm::countl_zero<uint32_t>(Lo_32(Imm));
1013e8d8bef9SDimitry Andric   if ((HiTZ + LoLZ) >= Num)
1014e8d8bef9SDimitry Andric     return (32 + HiTZ);
1015e8d8bef9SDimitry Andric   return 0;
1016e8d8bef9SDimitry Andric }
1017e8d8bef9SDimitry Andric 
1018e8d8bef9SDimitry Andric // Direct materialization of 64-bit constants by enumerated patterns.
selectI64ImmDirect(SelectionDAG * CurDAG,const SDLoc & dl,uint64_t Imm,unsigned & InstCnt)1019e8d8bef9SDimitry Andric static SDNode *selectI64ImmDirect(SelectionDAG *CurDAG, const SDLoc &dl,
1020e8d8bef9SDimitry Andric                                   uint64_t Imm, unsigned &InstCnt) {
102106c3fb27SDimitry Andric   unsigned TZ = llvm::countr_zero<uint64_t>(Imm);
102206c3fb27SDimitry Andric   unsigned LZ = llvm::countl_zero<uint64_t>(Imm);
102306c3fb27SDimitry Andric   unsigned TO = llvm::countr_one<uint64_t>(Imm);
102406c3fb27SDimitry Andric   unsigned LO = llvm::countl_one<uint64_t>(Imm);
1025e8d8bef9SDimitry Andric   unsigned Hi32 = Hi_32(Imm);
1026e8d8bef9SDimitry Andric   unsigned Lo32 = Lo_32(Imm);
1027e8d8bef9SDimitry Andric   SDNode *Result = nullptr;
1028e8d8bef9SDimitry Andric   unsigned Shift = 0;
1029e8d8bef9SDimitry Andric 
1030e8d8bef9SDimitry Andric   auto getI32Imm = [CurDAG, dl](unsigned Imm) {
1031e8d8bef9SDimitry Andric     return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
1032e8d8bef9SDimitry Andric   };
1033e8d8bef9SDimitry Andric 
1034e8d8bef9SDimitry Andric   // Following patterns use 1 instructions to materialize the Imm.
1035e8d8bef9SDimitry Andric   InstCnt = 1;
1036e8d8bef9SDimitry Andric   // 1-1) Patterns : {zeros}{15-bit valve}
1037e8d8bef9SDimitry Andric   //                 {ones}{15-bit valve}
1038e8d8bef9SDimitry Andric   if (isInt<16>(Imm)) {
1039e8d8bef9SDimitry Andric     SDValue SDImm = CurDAG->getTargetConstant(Imm, dl, MVT::i64);
1040e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, SDImm);
1041e8d8bef9SDimitry Andric   }
1042e8d8bef9SDimitry Andric   // 1-2) Patterns : {zeros}{15-bit valve}{16 zeros}
1043e8d8bef9SDimitry Andric   //                 {ones}{15-bit valve}{16 zeros}
1044e8d8bef9SDimitry Andric   if (TZ > 15 && (LZ > 32 || LO > 32))
1045e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64,
1046e8d8bef9SDimitry Andric                                   getI32Imm((Imm >> 16) & 0xffff));
1047e8d8bef9SDimitry Andric 
1048e8d8bef9SDimitry Andric   // Following patterns use 2 instructions to materialize the Imm.
1049e8d8bef9SDimitry Andric   InstCnt = 2;
1050e8d8bef9SDimitry Andric   assert(LZ < 64 && "Unexpected leading zeros here.");
1051e8d8bef9SDimitry Andric   // Count of ones follwing the leading zeros.
105206c3fb27SDimitry Andric   unsigned FO = llvm::countl_one<uint64_t>(Imm << LZ);
1053e8d8bef9SDimitry Andric   // 2-1) Patterns : {zeros}{31-bit value}
1054e8d8bef9SDimitry Andric   //                 {ones}{31-bit value}
1055e8d8bef9SDimitry Andric   if (isInt<32>(Imm)) {
1056e8d8bef9SDimitry Andric     uint64_t ImmHi16 = (Imm >> 16) & 0xffff;
1057e8d8bef9SDimitry Andric     unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
1058e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(Opcode, dl, MVT::i64, getI32Imm(ImmHi16));
1059e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
1060e8d8bef9SDimitry Andric                                   getI32Imm(Imm & 0xffff));
1061e8d8bef9SDimitry Andric   }
1062e8d8bef9SDimitry Andric   // 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros}
1063e8d8bef9SDimitry Andric   //                 {zeros}{15-bit value}{zeros}
1064e8d8bef9SDimitry Andric   //                 {zeros}{ones}{15-bit value}
1065e8d8bef9SDimitry Andric   //                 {ones}{15-bit value}{zeros}
1066e8d8bef9SDimitry Andric   // We can take advantage of LI's sign-extension semantics to generate leading
1067e8d8bef9SDimitry Andric   // ones, and then use RLDIC to mask off the ones in both sides after rotation.
1068e8d8bef9SDimitry Andric   if ((LZ + FO + TZ) > 48) {
1069e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
1070e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> TZ) & 0xffff));
1071e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, SDValue(Result, 0),
1072e8d8bef9SDimitry Andric                                   getI32Imm(TZ), getI32Imm(LZ));
1073e8d8bef9SDimitry Andric   }
1074e8d8bef9SDimitry Andric   // 2-3) Pattern : {zeros}{15-bit value}{ones}
1075e8d8bef9SDimitry Andric   // Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value,
1076e8d8bef9SDimitry Andric   // therefore we can take advantage of LI's sign-extension semantics, and then
1077e8d8bef9SDimitry Andric   // mask them off after rotation.
1078e8d8bef9SDimitry Andric   //
1079e8d8bef9SDimitry Andric   // +--LZ--||-15-bit-||--TO--+     +-------------|--16-bit--+
1080e8d8bef9SDimitry Andric   // |00000001bbbbbbbbb1111111| ->  |00000000000001bbbbbbbbb1|
1081e8d8bef9SDimitry Andric   // +------------------------+     +------------------------+
1082e8d8bef9SDimitry Andric   // 63                      0      63                      0
1083e8d8bef9SDimitry Andric   //          Imm                   (Imm >> (48 - LZ) & 0xffff)
1084e8d8bef9SDimitry Andric   // +----sext-----|--16-bit--+     +clear-|-----------------+
1085e8d8bef9SDimitry Andric   // |11111111111111bbbbbbbbb1| ->  |00000001bbbbbbbbb1111111|
1086e8d8bef9SDimitry Andric   // +------------------------+     +------------------------+
1087e8d8bef9SDimitry Andric   // 63                      0      63                      0
1088e8d8bef9SDimitry Andric   // LI8: sext many leading zeros   RLDICL: rotate left (48 - LZ), clear left LZ
1089e8d8bef9SDimitry Andric   if ((LZ + TO) > 48) {
1090e8d8bef9SDimitry Andric     // Since the immediates with (LZ > 32) have been handled by previous
1091e8d8bef9SDimitry Andric     // patterns, here we have (LZ <= 32) to make sure we will not shift right
1092e8d8bef9SDimitry Andric     // the Imm by a negative value.
1093e8d8bef9SDimitry Andric     assert(LZ <= 32 && "Unexpected shift value.");
1094e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
1095e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> (48 - LZ) & 0xffff)));
1096e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1097e8d8bef9SDimitry Andric                                   getI32Imm(48 - LZ), getI32Imm(LZ));
1098e8d8bef9SDimitry Andric   }
1099e8d8bef9SDimitry Andric   // 2-4) Patterns : {zeros}{ones}{15-bit value}{ones}
1100e8d8bef9SDimitry Andric   //                 {ones}{15-bit value}{ones}
1101e8d8bef9SDimitry Andric   // We can take advantage of LI's sign-extension semantics to generate leading
1102e8d8bef9SDimitry Andric   // ones, and then use RLDICL to mask off the ones in left sides (if required)
1103e8d8bef9SDimitry Andric   // after rotation.
1104e8d8bef9SDimitry Andric   //
1105e8d8bef9SDimitry Andric   // +-LZ-FO||-15-bit-||--TO--+     +-------------|--16-bit--+
1106e8d8bef9SDimitry Andric   // |00011110bbbbbbbbb1111111| ->  |000000000011110bbbbbbbbb|
1107e8d8bef9SDimitry Andric   // +------------------------+     +------------------------+
1108e8d8bef9SDimitry Andric   // 63                      0      63                      0
1109e8d8bef9SDimitry Andric   //            Imm                    (Imm >> TO) & 0xffff
1110e8d8bef9SDimitry Andric   // +----sext-----|--16-bit--+     +LZ|---------------------+
1111e8d8bef9SDimitry Andric   // |111111111111110bbbbbbbbb| ->  |00011110bbbbbbbbb1111111|
1112e8d8bef9SDimitry Andric   // +------------------------+     +------------------------+
1113e8d8bef9SDimitry Andric   // 63                      0      63                      0
1114e8d8bef9SDimitry Andric   // LI8: sext many leading zeros   RLDICL: rotate left TO, clear left LZ
1115e8d8bef9SDimitry Andric   if ((LZ + FO + TO) > 48) {
1116e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
1117e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> TO) & 0xffff));
1118e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1119e8d8bef9SDimitry Andric                                   getI32Imm(TO), getI32Imm(LZ));
1120e8d8bef9SDimitry Andric   }
1121e8d8bef9SDimitry Andric   // 2-5) Pattern : {32 zeros}{****}{0}{15-bit value}
1122e8d8bef9SDimitry Andric   // If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit
1123e8d8bef9SDimitry Andric   // value, we can use LI for Lo16 without generating leading ones then add the
1124e8d8bef9SDimitry Andric   // Hi16(in Lo32).
1125e8d8bef9SDimitry Andric   if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {
1126e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
1127e8d8bef9SDimitry Andric                                     getI32Imm(Lo32 & 0xffff));
1128e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::ORIS8, dl, MVT::i64, SDValue(Result, 0),
1129e8d8bef9SDimitry Andric                                   getI32Imm(Lo32 >> 16));
1130e8d8bef9SDimitry Andric   }
1131e8d8bef9SDimitry Andric   // 2-6) Patterns : {******}{49 zeros}{******}
1132e8d8bef9SDimitry Andric   //                 {******}{49 ones}{******}
1133e8d8bef9SDimitry Andric   // If the Imm contains 49 consecutive zeros/ones, it means that a total of 15
1134e8d8bef9SDimitry Andric   // bits remain on both sides. Rotate right the Imm to construct an int<16>
1135e8d8bef9SDimitry Andric   // value, use LI for int<16> value and then use RLDICL without mask to rotate
1136e8d8bef9SDimitry Andric   // it back.
1137e8d8bef9SDimitry Andric   //
1138e8d8bef9SDimitry Andric   // 1) findContiguousZerosAtLeast(Imm, 49)
1139e8d8bef9SDimitry Andric   // +------|--zeros-|------+     +---ones--||---15 bit--+
1140e8d8bef9SDimitry Andric   // |bbbbbb0000000000aaaaaa| ->  |0000000000aaaaaabbbbbb|
1141e8d8bef9SDimitry Andric   // +----------------------+     +----------------------+
1142e8d8bef9SDimitry Andric   // 63                    0      63                    0
1143e8d8bef9SDimitry Andric   //
1144e8d8bef9SDimitry Andric   // 2) findContiguousZerosAtLeast(~Imm, 49)
1145e8d8bef9SDimitry Andric   // +------|--ones--|------+     +---ones--||---15 bit--+
1146e8d8bef9SDimitry Andric   // |bbbbbb1111111111aaaaaa| ->  |1111111111aaaaaabbbbbb|
1147e8d8bef9SDimitry Andric   // +----------------------+     +----------------------+
1148e8d8bef9SDimitry Andric   // 63                    0      63                    0
1149e8d8bef9SDimitry Andric   if ((Shift = findContiguousZerosAtLeast(Imm, 49)) ||
1150e8d8bef9SDimitry Andric       (Shift = findContiguousZerosAtLeast(~Imm, 49))) {
1151fe6060f1SDimitry Andric     uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
1152e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64,
1153e8d8bef9SDimitry Andric                                     getI32Imm(RotImm & 0xffff));
1154e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1155e8d8bef9SDimitry Andric                                   getI32Imm(Shift), getI32Imm(0));
1156e8d8bef9SDimitry Andric   }
11575f757f3fSDimitry Andric   // 2-7) Patterns : High word == Low word
11585f757f3fSDimitry Andric   // This may require 2 to 3 instructions, depending on whether Lo32 can be
11595f757f3fSDimitry Andric   // materialized in 1 instruction.
11605f757f3fSDimitry Andric   if (Hi32 == Lo32) {
11615f757f3fSDimitry Andric     // Handle the first 32 bits.
11625f757f3fSDimitry Andric     uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;
11635f757f3fSDimitry Andric     uint64_t ImmLo16 = Lo32 & 0xffff;
11645f757f3fSDimitry Andric     if (isInt<16>(Lo32))
11655f757f3fSDimitry Andric       Result =
11665f757f3fSDimitry Andric           CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, getI32Imm(ImmLo16));
11675f757f3fSDimitry Andric     else if (!ImmLo16)
11685f757f3fSDimitry Andric       Result =
11695f757f3fSDimitry Andric           CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(ImmHi16));
11705f757f3fSDimitry Andric     else {
11715f757f3fSDimitry Andric       InstCnt = 3;
11725f757f3fSDimitry Andric       Result =
11735f757f3fSDimitry Andric           CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(ImmHi16));
11745f757f3fSDimitry Andric       Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64,
11755f757f3fSDimitry Andric                                       SDValue(Result, 0), getI32Imm(ImmLo16));
11765f757f3fSDimitry Andric     }
11775f757f3fSDimitry Andric     // Use rldimi to insert the Low word into High word.
11785f757f3fSDimitry Andric     SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32),
11795f757f3fSDimitry Andric                      getI32Imm(0)};
11805f757f3fSDimitry Andric     return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
11815f757f3fSDimitry Andric   }
1182e8d8bef9SDimitry Andric 
1183e8d8bef9SDimitry Andric   // Following patterns use 3 instructions to materialize the Imm.
1184e8d8bef9SDimitry Andric   InstCnt = 3;
1185e8d8bef9SDimitry Andric   // 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros}
1186e8d8bef9SDimitry Andric   //                 {zeros}{31-bit value}{zeros}
1187e8d8bef9SDimitry Andric   //                 {zeros}{ones}{31-bit value}
1188e8d8bef9SDimitry Andric   //                 {ones}{31-bit value}{zeros}
1189e8d8bef9SDimitry Andric   // We can take advantage of LIS's sign-extension semantics to generate leading
1190e8d8bef9SDimitry Andric   // ones, add the remaining bits with ORI, and then use RLDIC to mask off the
1191e8d8bef9SDimitry Andric   // ones in both sides after rotation.
1192e8d8bef9SDimitry Andric   if ((LZ + FO + TZ) > 32) {
1193e8d8bef9SDimitry Andric     uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff;
1194e8d8bef9SDimitry Andric     unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
1195e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(Opcode, dl, MVT::i64, getI32Imm(ImmHi16));
1196e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
1197e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> TZ) & 0xffff));
1198e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, SDValue(Result, 0),
1199e8d8bef9SDimitry Andric                                   getI32Imm(TZ), getI32Imm(LZ));
1200e8d8bef9SDimitry Andric   }
1201e8d8bef9SDimitry Andric   // 3-2) Pattern : {zeros}{31-bit value}{ones}
1202bdd1243dSDimitry Andric   // Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits
1203bdd1243dSDimitry Andric   // value, therefore we can take advantage of LIS's sign-extension semantics,
1204bdd1243dSDimitry Andric   // add the remaining bits with ORI, and then mask them off after rotation.
1205e8d8bef9SDimitry Andric   // This is similar to Pattern 2-3, please refer to the diagram there.
1206e8d8bef9SDimitry Andric   if ((LZ + TO) > 32) {
1207e8d8bef9SDimitry Andric     // Since the immediates with (LZ > 32) have been handled by previous
1208e8d8bef9SDimitry Andric     // patterns, here we have (LZ <= 32) to make sure we will not shift right
1209e8d8bef9SDimitry Andric     // the Imm by a negative value.
1210e8d8bef9SDimitry Andric     assert(LZ <= 32 && "Unexpected shift value.");
1211e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64,
1212e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> (48 - LZ)) & 0xffff));
1213e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
1214e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> (32 - LZ)) & 0xffff));
1215e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1216e8d8bef9SDimitry Andric                                   getI32Imm(32 - LZ), getI32Imm(LZ));
1217e8d8bef9SDimitry Andric   }
1218e8d8bef9SDimitry Andric   // 3-3) Patterns : {zeros}{ones}{31-bit value}{ones}
1219e8d8bef9SDimitry Andric   //                 {ones}{31-bit value}{ones}
1220e8d8bef9SDimitry Andric   // We can take advantage of LIS's sign-extension semantics to generate leading
1221e8d8bef9SDimitry Andric   // ones, add the remaining bits with ORI, and then use RLDICL to mask off the
1222e8d8bef9SDimitry Andric   // ones in left sides (if required) after rotation.
1223e8d8bef9SDimitry Andric   // This is similar to Pattern 2-4, please refer to the diagram there.
1224e8d8bef9SDimitry Andric   if ((LZ + FO + TO) > 32) {
1225e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64,
1226e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> (TO + 16)) & 0xffff));
1227e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
1228e8d8bef9SDimitry Andric                                     getI32Imm((Imm >> TO) & 0xffff));
1229e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1230e8d8bef9SDimitry Andric                                   getI32Imm(TO), getI32Imm(LZ));
1231e8d8bef9SDimitry Andric   }
12325f757f3fSDimitry Andric   // 3-4) Patterns : {******}{33 zeros}{******}
1233e8d8bef9SDimitry Andric   //                 {******}{33 ones}{******}
1234e8d8bef9SDimitry Andric   // If the Imm contains 33 consecutive zeros/ones, it means that a total of 31
1235e8d8bef9SDimitry Andric   // bits remain on both sides. Rotate right the Imm to construct an int<32>
1236e8d8bef9SDimitry Andric   // value, use LIS + ORI for int<32> value and then use RLDICL without mask to
1237e8d8bef9SDimitry Andric   // rotate it back.
1238e8d8bef9SDimitry Andric   // This is similar to Pattern 2-6, please refer to the diagram there.
1239e8d8bef9SDimitry Andric   if ((Shift = findContiguousZerosAtLeast(Imm, 33)) ||
1240e8d8bef9SDimitry Andric       (Shift = findContiguousZerosAtLeast(~Imm, 33))) {
1241fe6060f1SDimitry Andric     uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
1242e8d8bef9SDimitry Andric     uint64_t ImmHi16 = (RotImm >> 16) & 0xffff;
1243e8d8bef9SDimitry Andric     unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
1244e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(Opcode, dl, MVT::i64, getI32Imm(ImmHi16));
1245e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
1246e8d8bef9SDimitry Andric                                     getI32Imm(RotImm & 0xffff));
1247e8d8bef9SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1248e8d8bef9SDimitry Andric                                   getI32Imm(Shift), getI32Imm(0));
1249e8d8bef9SDimitry Andric   }
1250e8d8bef9SDimitry Andric 
1251e8d8bef9SDimitry Andric   InstCnt = 0;
1252e8d8bef9SDimitry Andric   return nullptr;
1253e8d8bef9SDimitry Andric }
1254e8d8bef9SDimitry Andric 
1255fe6060f1SDimitry Andric // Try to select instructions to generate a 64 bit immediate using prefix as
1256fe6060f1SDimitry Andric // well as non prefix instructions. The function will return the SDNode
1257fe6060f1SDimitry Andric // to materialize that constant or it will return nullptr if it does not
1258fe6060f1SDimitry Andric // find one. The variable InstCnt is set to the number of instructions that
1259fe6060f1SDimitry Andric // were selected.
selectI64ImmDirectPrefix(SelectionDAG * CurDAG,const SDLoc & dl,uint64_t Imm,unsigned & InstCnt)1260fe6060f1SDimitry Andric static SDNode *selectI64ImmDirectPrefix(SelectionDAG *CurDAG, const SDLoc &dl,
1261fe6060f1SDimitry Andric                                         uint64_t Imm, unsigned &InstCnt) {
126206c3fb27SDimitry Andric   unsigned TZ = llvm::countr_zero<uint64_t>(Imm);
126306c3fb27SDimitry Andric   unsigned LZ = llvm::countl_zero<uint64_t>(Imm);
126406c3fb27SDimitry Andric   unsigned TO = llvm::countr_one<uint64_t>(Imm);
126506c3fb27SDimitry Andric   unsigned FO = llvm::countl_one<uint64_t>(LZ == 64 ? 0 : (Imm << LZ));
1266fe6060f1SDimitry Andric   unsigned Hi32 = Hi_32(Imm);
1267fe6060f1SDimitry Andric   unsigned Lo32 = Lo_32(Imm);
1268fe6060f1SDimitry Andric 
1269fe6060f1SDimitry Andric   auto getI32Imm = [CurDAG, dl](unsigned Imm) {
1270fe6060f1SDimitry Andric     return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
1271fe6060f1SDimitry Andric   };
1272fe6060f1SDimitry Andric 
1273fe6060f1SDimitry Andric   auto getI64Imm = [CurDAG, dl](uint64_t Imm) {
1274fe6060f1SDimitry Andric     return CurDAG->getTargetConstant(Imm, dl, MVT::i64);
1275fe6060f1SDimitry Andric   };
1276fe6060f1SDimitry Andric 
1277fe6060f1SDimitry Andric   // Following patterns use 1 instruction to materialize Imm.
1278fe6060f1SDimitry Andric   InstCnt = 1;
1279fe6060f1SDimitry Andric 
1280fe6060f1SDimitry Andric   // The pli instruction can materialize up to 34 bits directly.
1281fe6060f1SDimitry Andric   // If a constant fits within 34-bits, emit the pli instruction here directly.
1282fe6060f1SDimitry Andric   if (isInt<34>(Imm))
1283fe6060f1SDimitry Andric     return CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
1284fe6060f1SDimitry Andric                                   CurDAG->getTargetConstant(Imm, dl, MVT::i64));
1285fe6060f1SDimitry Andric 
1286fe6060f1SDimitry Andric   // Require at least two instructions.
1287fe6060f1SDimitry Andric   InstCnt = 2;
1288fe6060f1SDimitry Andric   SDNode *Result = nullptr;
1289fe6060f1SDimitry Andric   // Patterns : {zeros}{ones}{33-bit value}{zeros}
1290fe6060f1SDimitry Andric   //            {zeros}{33-bit value}{zeros}
1291fe6060f1SDimitry Andric   //            {zeros}{ones}{33-bit value}
1292fe6060f1SDimitry Andric   //            {ones}{33-bit value}{zeros}
1293fe6060f1SDimitry Andric   // We can take advantage of PLI's sign-extension semantics to generate leading
1294fe6060f1SDimitry Andric   // ones, and then use RLDIC to mask off the ones on both sides after rotation.
1295fe6060f1SDimitry Andric   if ((LZ + FO + TZ) > 30) {
1296fe6060f1SDimitry Andric     APInt SignedInt34 = APInt(34, (Imm >> TZ) & 0x3ffffffff);
1297fe6060f1SDimitry Andric     APInt Extended = SignedInt34.sext(64);
1298fe6060f1SDimitry Andric     Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
1299fe6060f1SDimitry Andric                                     getI64Imm(*Extended.getRawData()));
1300fe6060f1SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, SDValue(Result, 0),
1301fe6060f1SDimitry Andric                                   getI32Imm(TZ), getI32Imm(LZ));
1302fe6060f1SDimitry Andric   }
1303fe6060f1SDimitry Andric   // Pattern : {zeros}{33-bit value}{ones}
1304fe6060f1SDimitry Andric   // Shift right the Imm by (30 - LZ) bits to construct a negative 34 bit value,
1305fe6060f1SDimitry Andric   // therefore we can take advantage of PLI's sign-extension semantics, and then
1306fe6060f1SDimitry Andric   // mask them off after rotation.
1307fe6060f1SDimitry Andric   //
1308fe6060f1SDimitry Andric   // +--LZ--||-33-bit-||--TO--+     +-------------|--34-bit--+
1309fe6060f1SDimitry Andric   // |00000001bbbbbbbbb1111111| ->  |00000000000001bbbbbbbbb1|
1310fe6060f1SDimitry Andric   // +------------------------+     +------------------------+
1311fe6060f1SDimitry Andric   // 63                      0      63                      0
1312fe6060f1SDimitry Andric   //
1313fe6060f1SDimitry Andric   // +----sext-----|--34-bit--+     +clear-|-----------------+
1314fe6060f1SDimitry Andric   // |11111111111111bbbbbbbbb1| ->  |00000001bbbbbbbbb1111111|
1315fe6060f1SDimitry Andric   // +------------------------+     +------------------------+
1316fe6060f1SDimitry Andric   // 63                      0      63                      0
1317fe6060f1SDimitry Andric   if ((LZ + TO) > 30) {
1318fe6060f1SDimitry Andric     APInt SignedInt34 = APInt(34, (Imm >> (30 - LZ)) & 0x3ffffffff);
1319fe6060f1SDimitry Andric     APInt Extended = SignedInt34.sext(64);
1320fe6060f1SDimitry Andric     Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
1321fe6060f1SDimitry Andric                                     getI64Imm(*Extended.getRawData()));
1322fe6060f1SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1323fe6060f1SDimitry Andric                                   getI32Imm(30 - LZ), getI32Imm(LZ));
1324fe6060f1SDimitry Andric   }
1325fe6060f1SDimitry Andric   // Patterns : {zeros}{ones}{33-bit value}{ones}
1326fe6060f1SDimitry Andric   //            {ones}{33-bit value}{ones}
1327fe6060f1SDimitry Andric   // Similar to LI we can take advantage of PLI's sign-extension semantics to
1328fe6060f1SDimitry Andric   // generate leading ones, and then use RLDICL to mask off the ones in left
1329fe6060f1SDimitry Andric   // sides (if required) after rotation.
1330fe6060f1SDimitry Andric   if ((LZ + FO + TO) > 30) {
1331fe6060f1SDimitry Andric     APInt SignedInt34 = APInt(34, (Imm >> TO) & 0x3ffffffff);
1332fe6060f1SDimitry Andric     APInt Extended = SignedInt34.sext(64);
1333fe6060f1SDimitry Andric     Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64,
1334fe6060f1SDimitry Andric                                     getI64Imm(*Extended.getRawData()));
1335fe6060f1SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, SDValue(Result, 0),
1336fe6060f1SDimitry Andric                                   getI32Imm(TO), getI32Imm(LZ));
1337fe6060f1SDimitry Andric   }
1338fe6060f1SDimitry Andric   // Patterns : {******}{31 zeros}{******}
1339fe6060f1SDimitry Andric   //          : {******}{31 ones}{******}
1340fe6060f1SDimitry Andric   // If Imm contains 31 consecutive zeros/ones then the remaining bit count
1341fe6060f1SDimitry Andric   // is 33. Rotate right the Imm to construct a int<33> value, we can use PLI
1342fe6060f1SDimitry Andric   // for the int<33> value and then use RLDICL without a mask to rotate it back.
1343fe6060f1SDimitry Andric   //
1344fe6060f1SDimitry Andric   // +------|--ones--|------+     +---ones--||---33 bit--+
1345fe6060f1SDimitry Andric   // |bbbbbb1111111111aaaaaa| ->  |1111111111aaaaaabbbbbb|
1346fe6060f1SDimitry Andric   // +----------------------+     +----------------------+
1347fe6060f1SDimitry Andric   // 63                    0      63                    0
1348fe6060f1SDimitry Andric   for (unsigned Shift = 0; Shift < 63; ++Shift) {
1349fe6060f1SDimitry Andric     uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
1350fe6060f1SDimitry Andric     if (isInt<34>(RotImm)) {
1351fe6060f1SDimitry Andric       Result =
1352fe6060f1SDimitry Andric           CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(RotImm));
1353fe6060f1SDimitry Andric       return CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
1354fe6060f1SDimitry Andric                                     SDValue(Result, 0), getI32Imm(Shift),
1355fe6060f1SDimitry Andric                                     getI32Imm(0));
1356fe6060f1SDimitry Andric     }
1357fe6060f1SDimitry Andric   }
1358fe6060f1SDimitry Andric 
1359fe6060f1SDimitry Andric   // Patterns : High word == Low word
1360fe6060f1SDimitry Andric   // This is basically a splat of a 32 bit immediate.
1361fe6060f1SDimitry Andric   if (Hi32 == Lo32) {
1362fe6060f1SDimitry Andric     Result = CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(Hi32));
1363fe6060f1SDimitry Andric     SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32),
1364fe6060f1SDimitry Andric                      getI32Imm(0)};
1365fe6060f1SDimitry Andric     return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
1366fe6060f1SDimitry Andric   }
1367fe6060f1SDimitry Andric 
1368fe6060f1SDimitry Andric   InstCnt = 3;
1369fe6060f1SDimitry Andric   // Catch-all
1370fe6060f1SDimitry Andric   // This pattern can form any 64 bit immediate in 3 instructions.
1371fe6060f1SDimitry Andric   SDNode *ResultHi =
1372fe6060f1SDimitry Andric       CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(Hi32));
1373fe6060f1SDimitry Andric   SDNode *ResultLo =
1374fe6060f1SDimitry Andric       CurDAG->getMachineNode(PPC::PLI8, dl, MVT::i64, getI64Imm(Lo32));
1375fe6060f1SDimitry Andric   SDValue Ops[] = {SDValue(ResultLo, 0), SDValue(ResultHi, 0), getI32Imm(32),
1376fe6060f1SDimitry Andric                    getI32Imm(0)};
1377fe6060f1SDimitry Andric   return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
1378fe6060f1SDimitry Andric }
1379fe6060f1SDimitry Andric 
selectI64Imm(SelectionDAG * CurDAG,const SDLoc & dl,uint64_t Imm,unsigned * InstCnt=nullptr)1380e8d8bef9SDimitry Andric static SDNode *selectI64Imm(SelectionDAG *CurDAG, const SDLoc &dl, uint64_t Imm,
1381e8d8bef9SDimitry Andric                             unsigned *InstCnt = nullptr) {
1382e8d8bef9SDimitry Andric   unsigned InstCntDirect = 0;
1383bdd1243dSDimitry Andric   // No more than 3 instructions are used if we can select the i64 immediate
1384e8d8bef9SDimitry Andric   // directly.
1385e8d8bef9SDimitry Andric   SDNode *Result = selectI64ImmDirect(CurDAG, dl, Imm, InstCntDirect);
1386fe6060f1SDimitry Andric 
1387fe6060f1SDimitry Andric   const PPCSubtarget &Subtarget =
1388fe6060f1SDimitry Andric       CurDAG->getMachineFunction().getSubtarget<PPCSubtarget>();
1389fe6060f1SDimitry Andric 
1390fe6060f1SDimitry Andric   // If we have prefixed instructions and there is a chance we can
1391fe6060f1SDimitry Andric   // materialize the constant with fewer prefixed instructions than
1392fe6060f1SDimitry Andric   // non-prefixed, try that.
1393fe6060f1SDimitry Andric   if (Subtarget.hasPrefixInstrs() && InstCntDirect != 1) {
1394fe6060f1SDimitry Andric     unsigned InstCntDirectP = 0;
1395fe6060f1SDimitry Andric     SDNode *ResultP = selectI64ImmDirectPrefix(CurDAG, dl, Imm, InstCntDirectP);
1396fe6060f1SDimitry Andric     // Use the prefix case in either of two cases:
1397fe6060f1SDimitry Andric     // 1) We have no result from the non-prefix case to use.
1398fe6060f1SDimitry Andric     // 2) The non-prefix case uses more instructions than the prefix case.
1399fe6060f1SDimitry Andric     // If the prefix and non-prefix cases use the same number of instructions
1400fe6060f1SDimitry Andric     // we will prefer the non-prefix case.
1401fe6060f1SDimitry Andric     if (ResultP && (!Result || InstCntDirectP < InstCntDirect)) {
1402fe6060f1SDimitry Andric       if (InstCnt)
1403fe6060f1SDimitry Andric         *InstCnt = InstCntDirectP;
1404fe6060f1SDimitry Andric       return ResultP;
1405fe6060f1SDimitry Andric     }
1406fe6060f1SDimitry Andric   }
1407fe6060f1SDimitry Andric 
1408e8d8bef9SDimitry Andric   if (Result) {
1409e8d8bef9SDimitry Andric     if (InstCnt)
1410e8d8bef9SDimitry Andric       *InstCnt = InstCntDirect;
1411e8d8bef9SDimitry Andric     return Result;
1412e8d8bef9SDimitry Andric   }
1413e8d8bef9SDimitry Andric   auto getI32Imm = [CurDAG, dl](unsigned Imm) {
1414e8d8bef9SDimitry Andric     return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
1415e8d8bef9SDimitry Andric   };
141606c3fb27SDimitry Andric 
141706c3fb27SDimitry Andric   uint32_t Hi16OfLo32 = (Lo_32(Imm) >> 16) & 0xffff;
141806c3fb27SDimitry Andric   uint32_t Lo16OfLo32 = Lo_32(Imm) & 0xffff;
141906c3fb27SDimitry Andric 
142006c3fb27SDimitry Andric   // Try to use 4 instructions to materialize the immediate which is "almost" a
142106c3fb27SDimitry Andric   // splat of a 32 bit immediate.
142206c3fb27SDimitry Andric   if (Hi16OfLo32 && Lo16OfLo32) {
142306c3fb27SDimitry Andric     uint32_t Hi16OfHi32 = (Hi_32(Imm) >> 16) & 0xffff;
142406c3fb27SDimitry Andric     uint32_t Lo16OfHi32 = Hi_32(Imm) & 0xffff;
142506c3fb27SDimitry Andric     bool IsSelected = false;
142606c3fb27SDimitry Andric 
142706c3fb27SDimitry Andric     auto getSplat = [CurDAG, dl, getI32Imm](uint32_t Hi16, uint32_t Lo16) {
142806c3fb27SDimitry Andric       SDNode *Result =
142906c3fb27SDimitry Andric           CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(Hi16));
143006c3fb27SDimitry Andric       Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64,
143106c3fb27SDimitry Andric                                       SDValue(Result, 0), getI32Imm(Lo16));
143206c3fb27SDimitry Andric       SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32),
143306c3fb27SDimitry Andric                        getI32Imm(0)};
143406c3fb27SDimitry Andric       return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
143506c3fb27SDimitry Andric     };
143606c3fb27SDimitry Andric 
143706c3fb27SDimitry Andric     if (Hi16OfHi32 == Lo16OfHi32 && Lo16OfHi32 == Lo16OfLo32) {
143806c3fb27SDimitry Andric       IsSelected = true;
143906c3fb27SDimitry Andric       Result = getSplat(Hi16OfLo32, Lo16OfLo32);
144006c3fb27SDimitry Andric       // Modify Hi16OfHi32.
144106c3fb27SDimitry Andric       SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(48),
144206c3fb27SDimitry Andric                        getI32Imm(0)};
144306c3fb27SDimitry Andric       Result = CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops);
144406c3fb27SDimitry Andric     } else if (Hi16OfHi32 == Hi16OfLo32 && Hi16OfLo32 == Lo16OfLo32) {
144506c3fb27SDimitry Andric       IsSelected = true;
144606c3fb27SDimitry Andric       Result = getSplat(Hi16OfHi32, Lo16OfHi32);
144706c3fb27SDimitry Andric       // Modify Lo16OfLo32.
144806c3fb27SDimitry Andric       SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(16),
144906c3fb27SDimitry Andric                        getI32Imm(16), getI32Imm(31)};
145006c3fb27SDimitry Andric       Result = CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64, Ops);
145106c3fb27SDimitry Andric     } else if (Lo16OfHi32 == Lo16OfLo32 && Hi16OfLo32 == Lo16OfLo32) {
145206c3fb27SDimitry Andric       IsSelected = true;
145306c3fb27SDimitry Andric       Result = getSplat(Hi16OfHi32, Lo16OfHi32);
145406c3fb27SDimitry Andric       // Modify Hi16OfLo32.
145506c3fb27SDimitry Andric       SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(16),
145606c3fb27SDimitry Andric                        getI32Imm(0), getI32Imm(15)};
145706c3fb27SDimitry Andric       Result = CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64, Ops);
145806c3fb27SDimitry Andric     }
145906c3fb27SDimitry Andric     if (IsSelected == true) {
146006c3fb27SDimitry Andric       if (InstCnt)
146106c3fb27SDimitry Andric         *InstCnt = 4;
146206c3fb27SDimitry Andric       return Result;
146306c3fb27SDimitry Andric     }
146406c3fb27SDimitry Andric   }
146506c3fb27SDimitry Andric 
1466e8d8bef9SDimitry Andric   // Handle the upper 32 bit value.
1467e8d8bef9SDimitry Andric   Result =
1468e8d8bef9SDimitry Andric       selectI64ImmDirect(CurDAG, dl, Imm & 0xffffffff00000000, InstCntDirect);
1469e8d8bef9SDimitry Andric   // Add in the last bits as required.
147006c3fb27SDimitry Andric   if (Hi16OfLo32) {
1471e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::ORIS8, dl, MVT::i64,
147206c3fb27SDimitry Andric                                     SDValue(Result, 0), getI32Imm(Hi16OfLo32));
1473e8d8bef9SDimitry Andric     ++InstCntDirect;
1474e8d8bef9SDimitry Andric   }
147506c3fb27SDimitry Andric   if (Lo16OfLo32) {
1476e8d8bef9SDimitry Andric     Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, SDValue(Result, 0),
147706c3fb27SDimitry Andric                                     getI32Imm(Lo16OfLo32));
1478e8d8bef9SDimitry Andric     ++InstCntDirect;
1479e8d8bef9SDimitry Andric   }
1480e8d8bef9SDimitry Andric   if (InstCnt)
1481e8d8bef9SDimitry Andric     *InstCnt = InstCntDirect;
1482e8d8bef9SDimitry Andric   return Result;
1483e8d8bef9SDimitry Andric }
1484e8d8bef9SDimitry Andric 
14850b57cec5SDimitry Andric // Select a 64-bit constant.
selectI64Imm(SelectionDAG * CurDAG,SDNode * N)14860b57cec5SDimitry Andric static SDNode *selectI64Imm(SelectionDAG *CurDAG, SDNode *N) {
14870b57cec5SDimitry Andric   SDLoc dl(N);
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric   // Get 64 bit value.
14901db9f3b2SDimitry Andric   int64_t Imm = N->getAsZExtVal();
14910b57cec5SDimitry Andric   if (unsigned MinSize = allUsesTruncate(CurDAG, N)) {
14920b57cec5SDimitry Andric     uint64_t SextImm = SignExtend64(Imm, MinSize);
14930b57cec5SDimitry Andric     SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i64);
14940b57cec5SDimitry Andric     if (isInt<16>(SextImm))
14950b57cec5SDimitry Andric       return CurDAG->getMachineNode(PPC::LI8, dl, MVT::i64, SDImm);
14960b57cec5SDimitry Andric   }
14970b57cec5SDimitry Andric   return selectI64Imm(CurDAG, dl, Imm);
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric 
15000b57cec5SDimitry Andric namespace {
15010b57cec5SDimitry Andric 
15020b57cec5SDimitry Andric class BitPermutationSelector {
15030b57cec5SDimitry Andric   struct ValueBit {
15040b57cec5SDimitry Andric     SDValue V;
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric     // The bit number in the value, using a convention where bit 0 is the
15070b57cec5SDimitry Andric     // lowest-order bit.
15080b57cec5SDimitry Andric     unsigned Idx;
15090b57cec5SDimitry Andric 
15100b57cec5SDimitry Andric     // ConstZero means a bit we need to mask off.
15110b57cec5SDimitry Andric     // Variable is a bit comes from an input variable.
15120b57cec5SDimitry Andric     // VariableKnownToBeZero is also a bit comes from an input variable,
15130b57cec5SDimitry Andric     // but it is known to be already zero. So we do not need to mask them.
15140b57cec5SDimitry Andric     enum Kind {
15150b57cec5SDimitry Andric       ConstZero,
15160b57cec5SDimitry Andric       Variable,
15170b57cec5SDimitry Andric       VariableKnownToBeZero
15180b57cec5SDimitry Andric     } K;
15190b57cec5SDimitry Andric 
ValueBit__anon010aa3800711::BitPermutationSelector::ValueBit15200b57cec5SDimitry Andric     ValueBit(SDValue V, unsigned I, Kind K = Variable)
15210b57cec5SDimitry Andric       : V(V), Idx(I), K(K) {}
ValueBit__anon010aa3800711::BitPermutationSelector::ValueBit152204eeddc0SDimitry Andric     ValueBit(Kind K = Variable) : Idx(UINT32_MAX), K(K) {}
15230b57cec5SDimitry Andric 
isZero__anon010aa3800711::BitPermutationSelector::ValueBit15240b57cec5SDimitry Andric     bool isZero() const {
15250b57cec5SDimitry Andric       return K == ConstZero || K == VariableKnownToBeZero;
15260b57cec5SDimitry Andric     }
15270b57cec5SDimitry Andric 
hasValue__anon010aa3800711::BitPermutationSelector::ValueBit15280b57cec5SDimitry Andric     bool hasValue() const {
15290b57cec5SDimitry Andric       return K == Variable || K == VariableKnownToBeZero;
15300b57cec5SDimitry Andric     }
15310b57cec5SDimitry Andric 
getValue__anon010aa3800711::BitPermutationSelector::ValueBit15320b57cec5SDimitry Andric     SDValue getValue() const {
15330b57cec5SDimitry Andric       assert(hasValue() && "Cannot get the value of a constant bit");
15340b57cec5SDimitry Andric       return V;
15350b57cec5SDimitry Andric     }
15360b57cec5SDimitry Andric 
getValueBitIndex__anon010aa3800711::BitPermutationSelector::ValueBit15370b57cec5SDimitry Andric     unsigned getValueBitIndex() const {
15380b57cec5SDimitry Andric       assert(hasValue() && "Cannot get the value bit index of a constant bit");
15390b57cec5SDimitry Andric       return Idx;
15400b57cec5SDimitry Andric     }
15410b57cec5SDimitry Andric   };
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric   // A bit group has the same underlying value and the same rotate factor.
15440b57cec5SDimitry Andric   struct BitGroup {
15450b57cec5SDimitry Andric     SDValue V;
15460b57cec5SDimitry Andric     unsigned RLAmt;
15470b57cec5SDimitry Andric     unsigned StartIdx, EndIdx;
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric     // This rotation amount assumes that the lower 32 bits of the quantity are
15500b57cec5SDimitry Andric     // replicated in the high 32 bits by the rotation operator (which is done
15510b57cec5SDimitry Andric     // by rlwinm and friends in 64-bit mode).
15520b57cec5SDimitry Andric     bool Repl32;
15530b57cec5SDimitry Andric     // Did converting to Repl32 == true change the rotation factor? If it did,
15540b57cec5SDimitry Andric     // it decreased it by 32.
15550b57cec5SDimitry Andric     bool Repl32CR;
15560b57cec5SDimitry Andric     // Was this group coalesced after setting Repl32 to true?
15570b57cec5SDimitry Andric     bool Repl32Coalesced;
15580b57cec5SDimitry Andric 
BitGroup__anon010aa3800711::BitPermutationSelector::BitGroup15590b57cec5SDimitry Andric     BitGroup(SDValue V, unsigned R, unsigned S, unsigned E)
15600b57cec5SDimitry Andric       : V(V), RLAmt(R), StartIdx(S), EndIdx(E), Repl32(false), Repl32CR(false),
15610b57cec5SDimitry Andric         Repl32Coalesced(false) {
15620b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\tbit group for " << V.getNode() << " RLAmt = " << R
15630b57cec5SDimitry Andric                         << " [" << S << ", " << E << "]\n");
15640b57cec5SDimitry Andric     }
15650b57cec5SDimitry Andric   };
15660b57cec5SDimitry Andric 
15670b57cec5SDimitry Andric   // Information on each (Value, RLAmt) pair (like the number of groups
15680b57cec5SDimitry Andric   // associated with each) used to choose the lowering method.
15690b57cec5SDimitry Andric   struct ValueRotInfo {
15700b57cec5SDimitry Andric     SDValue V;
15710b57cec5SDimitry Andric     unsigned RLAmt = std::numeric_limits<unsigned>::max();
15720b57cec5SDimitry Andric     unsigned NumGroups = 0;
15730b57cec5SDimitry Andric     unsigned FirstGroupStartIdx = std::numeric_limits<unsigned>::max();
15740b57cec5SDimitry Andric     bool Repl32 = false;
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric     ValueRotInfo() = default;
15770b57cec5SDimitry Andric 
15780b57cec5SDimitry Andric     // For sorting (in reverse order) by NumGroups, and then by
15790b57cec5SDimitry Andric     // FirstGroupStartIdx.
operator <__anon010aa3800711::BitPermutationSelector::ValueRotInfo15800b57cec5SDimitry Andric     bool operator < (const ValueRotInfo &Other) const {
15810b57cec5SDimitry Andric       // We need to sort so that the non-Repl32 come first because, when we're
15820b57cec5SDimitry Andric       // doing masking, the Repl32 bit groups might be subsumed into the 64-bit
15830b57cec5SDimitry Andric       // masking operation.
15840b57cec5SDimitry Andric       if (Repl32 < Other.Repl32)
15850b57cec5SDimitry Andric         return true;
15860b57cec5SDimitry Andric       else if (Repl32 > Other.Repl32)
15870b57cec5SDimitry Andric         return false;
15880b57cec5SDimitry Andric       else if (NumGroups > Other.NumGroups)
15890b57cec5SDimitry Andric         return true;
15900b57cec5SDimitry Andric       else if (NumGroups < Other.NumGroups)
15910b57cec5SDimitry Andric         return false;
15920b57cec5SDimitry Andric       else if (RLAmt == 0 && Other.RLAmt != 0)
15930b57cec5SDimitry Andric         return true;
15940b57cec5SDimitry Andric       else if (RLAmt != 0 && Other.RLAmt == 0)
15950b57cec5SDimitry Andric         return false;
15960b57cec5SDimitry Andric       else if (FirstGroupStartIdx < Other.FirstGroupStartIdx)
15970b57cec5SDimitry Andric         return true;
15980b57cec5SDimitry Andric       return false;
15990b57cec5SDimitry Andric     }
16000b57cec5SDimitry Andric   };
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric   using ValueBitsMemoizedValue = std::pair<bool, SmallVector<ValueBit, 64>>;
16030b57cec5SDimitry Andric   using ValueBitsMemoizer =
16040b57cec5SDimitry Andric       DenseMap<SDValue, std::unique_ptr<ValueBitsMemoizedValue>>;
16050b57cec5SDimitry Andric   ValueBitsMemoizer Memoizer;
16060b57cec5SDimitry Andric 
16070b57cec5SDimitry Andric   // Return a pair of bool and a SmallVector pointer to a memoization entry.
16080b57cec5SDimitry Andric   // The bool is true if something interesting was deduced, otherwise if we're
16090b57cec5SDimitry Andric   // providing only a generic representation of V (or something else likewise
16100b57cec5SDimitry Andric   // uninteresting for instruction selection) through the SmallVector.
getValueBits(SDValue V,unsigned NumBits)16110b57cec5SDimitry Andric   std::pair<bool, SmallVector<ValueBit, 64> *> getValueBits(SDValue V,
16120b57cec5SDimitry Andric                                                             unsigned NumBits) {
16130b57cec5SDimitry Andric     auto &ValueEntry = Memoizer[V];
16140b57cec5SDimitry Andric     if (ValueEntry)
16150b57cec5SDimitry Andric       return std::make_pair(ValueEntry->first, &ValueEntry->second);
16160b57cec5SDimitry Andric     ValueEntry.reset(new ValueBitsMemoizedValue());
16170b57cec5SDimitry Andric     bool &Interesting = ValueEntry->first;
16180b57cec5SDimitry Andric     SmallVector<ValueBit, 64> &Bits = ValueEntry->second;
16190b57cec5SDimitry Andric     Bits.resize(NumBits);
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric     switch (V.getOpcode()) {
16220b57cec5SDimitry Andric     default: break;
16230b57cec5SDimitry Andric     case ISD::ROTL:
16240b57cec5SDimitry Andric       if (isa<ConstantSDNode>(V.getOperand(1))) {
162556727255SDimitry Andric         assert(isPowerOf2_32(NumBits) && "rotl bits should be power of 2!");
162656727255SDimitry Andric         unsigned RotAmt = V.getConstantOperandVal(1) & (NumBits - 1);
16270b57cec5SDimitry Andric 
16280b57cec5SDimitry Andric         const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
16290b57cec5SDimitry Andric 
16300b57cec5SDimitry Andric         for (unsigned i = 0; i < NumBits; ++i)
16310b57cec5SDimitry Andric           Bits[i] = LHSBits[i < RotAmt ? i + (NumBits - RotAmt) : i - RotAmt];
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric         return std::make_pair(Interesting = true, &Bits);
16340b57cec5SDimitry Andric       }
16350b57cec5SDimitry Andric       break;
16360b57cec5SDimitry Andric     case ISD::SHL:
1637e8d8bef9SDimitry Andric     case PPCISD::SHL:
16380b57cec5SDimitry Andric       if (isa<ConstantSDNode>(V.getOperand(1))) {
163956727255SDimitry Andric         // sld takes 7 bits, slw takes 6.
164056727255SDimitry Andric         unsigned ShiftAmt = V.getConstantOperandVal(1) & ((NumBits << 1) - 1);
16410b57cec5SDimitry Andric 
16420b57cec5SDimitry Andric         const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
16430b57cec5SDimitry Andric 
164456727255SDimitry Andric         if (ShiftAmt >= NumBits) {
164556727255SDimitry Andric           for (unsigned i = 0; i < NumBits; ++i)
164656727255SDimitry Andric             Bits[i] = ValueBit(ValueBit::ConstZero);
164756727255SDimitry Andric         } else {
16480b57cec5SDimitry Andric           for (unsigned i = ShiftAmt; i < NumBits; ++i)
16490b57cec5SDimitry Andric             Bits[i] = LHSBits[i - ShiftAmt];
16500b57cec5SDimitry Andric           for (unsigned i = 0; i < ShiftAmt; ++i)
16510b57cec5SDimitry Andric             Bits[i] = ValueBit(ValueBit::ConstZero);
165256727255SDimitry Andric         }
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric         return std::make_pair(Interesting = true, &Bits);
16550b57cec5SDimitry Andric       }
16560b57cec5SDimitry Andric       break;
16570b57cec5SDimitry Andric     case ISD::SRL:
1658e8d8bef9SDimitry Andric     case PPCISD::SRL:
16590b57cec5SDimitry Andric       if (isa<ConstantSDNode>(V.getOperand(1))) {
166056727255SDimitry Andric         // srd takes lowest 7 bits, srw takes 6.
166156727255SDimitry Andric         unsigned ShiftAmt = V.getConstantOperandVal(1) & ((NumBits << 1) - 1);
16620b57cec5SDimitry Andric 
16630b57cec5SDimitry Andric         const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
16640b57cec5SDimitry Andric 
166556727255SDimitry Andric         if (ShiftAmt >= NumBits) {
166656727255SDimitry Andric           for (unsigned i = 0; i < NumBits; ++i)
166756727255SDimitry Andric             Bits[i] = ValueBit(ValueBit::ConstZero);
166856727255SDimitry Andric         } else {
16690b57cec5SDimitry Andric           for (unsigned i = 0; i < NumBits - ShiftAmt; ++i)
16700b57cec5SDimitry Andric             Bits[i] = LHSBits[i + ShiftAmt];
16710b57cec5SDimitry Andric           for (unsigned i = NumBits - ShiftAmt; i < NumBits; ++i)
16720b57cec5SDimitry Andric             Bits[i] = ValueBit(ValueBit::ConstZero);
167356727255SDimitry Andric         }
16740b57cec5SDimitry Andric 
16750b57cec5SDimitry Andric         return std::make_pair(Interesting = true, &Bits);
16760b57cec5SDimitry Andric       }
16770b57cec5SDimitry Andric       break;
16780b57cec5SDimitry Andric     case ISD::AND:
16790b57cec5SDimitry Andric       if (isa<ConstantSDNode>(V.getOperand(1))) {
16800b57cec5SDimitry Andric         uint64_t Mask = V.getConstantOperandVal(1);
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric         const SmallVector<ValueBit, 64> *LHSBits;
16830b57cec5SDimitry Andric         // Mark this as interesting, only if the LHS was also interesting. This
16840b57cec5SDimitry Andric         // prevents the overall procedure from matching a single immediate 'and'
16850b57cec5SDimitry Andric         // (which is non-optimal because such an and might be folded with other
16860b57cec5SDimitry Andric         // things if we don't select it here).
16870b57cec5SDimitry Andric         std::tie(Interesting, LHSBits) = getValueBits(V.getOperand(0), NumBits);
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric         for (unsigned i = 0; i < NumBits; ++i)
16900b57cec5SDimitry Andric           if (((Mask >> i) & 1) == 1)
16910b57cec5SDimitry Andric             Bits[i] = (*LHSBits)[i];
16920b57cec5SDimitry Andric           else {
16930b57cec5SDimitry Andric             // AND instruction masks this bit. If the input is already zero,
16940b57cec5SDimitry Andric             // we have nothing to do here. Otherwise, make the bit ConstZero.
16950b57cec5SDimitry Andric             if ((*LHSBits)[i].isZero())
16960b57cec5SDimitry Andric               Bits[i] = (*LHSBits)[i];
16970b57cec5SDimitry Andric             else
16980b57cec5SDimitry Andric               Bits[i] = ValueBit(ValueBit::ConstZero);
16990b57cec5SDimitry Andric           }
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric         return std::make_pair(Interesting, &Bits);
17020b57cec5SDimitry Andric       }
17030b57cec5SDimitry Andric       break;
17040b57cec5SDimitry Andric     case ISD::OR: {
17050b57cec5SDimitry Andric       const auto &LHSBits = *getValueBits(V.getOperand(0), NumBits).second;
17060b57cec5SDimitry Andric       const auto &RHSBits = *getValueBits(V.getOperand(1), NumBits).second;
17070b57cec5SDimitry Andric 
17080b57cec5SDimitry Andric       bool AllDisjoint = true;
17090b57cec5SDimitry Andric       SDValue LastVal = SDValue();
17100b57cec5SDimitry Andric       unsigned LastIdx = 0;
17110b57cec5SDimitry Andric       for (unsigned i = 0; i < NumBits; ++i) {
17120b57cec5SDimitry Andric         if (LHSBits[i].isZero() && RHSBits[i].isZero()) {
17130b57cec5SDimitry Andric           // If both inputs are known to be zero and one is ConstZero and
17140b57cec5SDimitry Andric           // another is VariableKnownToBeZero, we can select whichever
17150b57cec5SDimitry Andric           // we like. To minimize the number of bit groups, we select
17160b57cec5SDimitry Andric           // VariableKnownToBeZero if this bit is the next bit of the same
17170b57cec5SDimitry Andric           // input variable from the previous bit. Otherwise, we select
17180b57cec5SDimitry Andric           // ConstZero.
17190b57cec5SDimitry Andric           if (LHSBits[i].hasValue() && LHSBits[i].getValue() == LastVal &&
17200b57cec5SDimitry Andric               LHSBits[i].getValueBitIndex() == LastIdx + 1)
17210b57cec5SDimitry Andric             Bits[i] = LHSBits[i];
17220b57cec5SDimitry Andric           else if (RHSBits[i].hasValue() && RHSBits[i].getValue() == LastVal &&
17230b57cec5SDimitry Andric                    RHSBits[i].getValueBitIndex() == LastIdx + 1)
17240b57cec5SDimitry Andric             Bits[i] = RHSBits[i];
17250b57cec5SDimitry Andric           else
17260b57cec5SDimitry Andric             Bits[i] = ValueBit(ValueBit::ConstZero);
17270b57cec5SDimitry Andric         }
17280b57cec5SDimitry Andric         else if (LHSBits[i].isZero())
17290b57cec5SDimitry Andric           Bits[i] = RHSBits[i];
17300b57cec5SDimitry Andric         else if (RHSBits[i].isZero())
17310b57cec5SDimitry Andric           Bits[i] = LHSBits[i];
17320b57cec5SDimitry Andric         else {
17330b57cec5SDimitry Andric           AllDisjoint = false;
17340b57cec5SDimitry Andric           break;
17350b57cec5SDimitry Andric         }
17360b57cec5SDimitry Andric         // We remember the value and bit index of this bit.
17370b57cec5SDimitry Andric         if (Bits[i].hasValue()) {
17380b57cec5SDimitry Andric           LastVal = Bits[i].getValue();
17390b57cec5SDimitry Andric           LastIdx = Bits[i].getValueBitIndex();
17400b57cec5SDimitry Andric         }
17410b57cec5SDimitry Andric         else {
17420b57cec5SDimitry Andric           if (LastVal) LastVal = SDValue();
17430b57cec5SDimitry Andric           LastIdx = 0;
17440b57cec5SDimitry Andric         }
17450b57cec5SDimitry Andric       }
17460b57cec5SDimitry Andric 
17470b57cec5SDimitry Andric       if (!AllDisjoint)
17480b57cec5SDimitry Andric         break;
17490b57cec5SDimitry Andric 
17500b57cec5SDimitry Andric       return std::make_pair(Interesting = true, &Bits);
17510b57cec5SDimitry Andric     }
17520b57cec5SDimitry Andric     case ISD::ZERO_EXTEND: {
17530b57cec5SDimitry Andric       // We support only the case with zero extension from i32 to i64 so far.
17540b57cec5SDimitry Andric       if (V.getValueType() != MVT::i64 ||
17550b57cec5SDimitry Andric           V.getOperand(0).getValueType() != MVT::i32)
17560b57cec5SDimitry Andric         break;
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric       const SmallVector<ValueBit, 64> *LHSBits;
17590b57cec5SDimitry Andric       const unsigned NumOperandBits = 32;
17600b57cec5SDimitry Andric       std::tie(Interesting, LHSBits) = getValueBits(V.getOperand(0),
17610b57cec5SDimitry Andric                                                     NumOperandBits);
17620b57cec5SDimitry Andric 
17630b57cec5SDimitry Andric       for (unsigned i = 0; i < NumOperandBits; ++i)
17640b57cec5SDimitry Andric         Bits[i] = (*LHSBits)[i];
17650b57cec5SDimitry Andric 
17660b57cec5SDimitry Andric       for (unsigned i = NumOperandBits; i < NumBits; ++i)
17670b57cec5SDimitry Andric         Bits[i] = ValueBit(ValueBit::ConstZero);
17680b57cec5SDimitry Andric 
17690b57cec5SDimitry Andric       return std::make_pair(Interesting, &Bits);
17700b57cec5SDimitry Andric     }
17710b57cec5SDimitry Andric     case ISD::TRUNCATE: {
17720b57cec5SDimitry Andric       EVT FromType = V.getOperand(0).getValueType();
17730b57cec5SDimitry Andric       EVT ToType = V.getValueType();
17740b57cec5SDimitry Andric       // We support only the case with truncate from i64 to i32.
17750b57cec5SDimitry Andric       if (FromType != MVT::i64 || ToType != MVT::i32)
17760b57cec5SDimitry Andric         break;
17770b57cec5SDimitry Andric       const unsigned NumAllBits = FromType.getSizeInBits();
17780b57cec5SDimitry Andric       SmallVector<ValueBit, 64> *InBits;
17790b57cec5SDimitry Andric       std::tie(Interesting, InBits) = getValueBits(V.getOperand(0),
17800b57cec5SDimitry Andric                                                     NumAllBits);
17810b57cec5SDimitry Andric       const unsigned NumValidBits = ToType.getSizeInBits();
17820b57cec5SDimitry Andric 
17830b57cec5SDimitry Andric       // A 32-bit instruction cannot touch upper 32-bit part of 64-bit value.
17840b57cec5SDimitry Andric       // So, we cannot include this truncate.
17850b57cec5SDimitry Andric       bool UseUpper32bit = false;
17860b57cec5SDimitry Andric       for (unsigned i = 0; i < NumValidBits; ++i)
17870b57cec5SDimitry Andric         if ((*InBits)[i].hasValue() && (*InBits)[i].getValueBitIndex() >= 32) {
17880b57cec5SDimitry Andric           UseUpper32bit = true;
17890b57cec5SDimitry Andric           break;
17900b57cec5SDimitry Andric         }
17910b57cec5SDimitry Andric       if (UseUpper32bit)
17920b57cec5SDimitry Andric         break;
17930b57cec5SDimitry Andric 
17940b57cec5SDimitry Andric       for (unsigned i = 0; i < NumValidBits; ++i)
17950b57cec5SDimitry Andric         Bits[i] = (*InBits)[i];
17960b57cec5SDimitry Andric 
17970b57cec5SDimitry Andric       return std::make_pair(Interesting, &Bits);
17980b57cec5SDimitry Andric     }
17990b57cec5SDimitry Andric     case ISD::AssertZext: {
18000b57cec5SDimitry Andric       // For AssertZext, we look through the operand and
18010b57cec5SDimitry Andric       // mark the bits known to be zero.
18020b57cec5SDimitry Andric       const SmallVector<ValueBit, 64> *LHSBits;
18030b57cec5SDimitry Andric       std::tie(Interesting, LHSBits) = getValueBits(V.getOperand(0),
18040b57cec5SDimitry Andric                                                     NumBits);
18050b57cec5SDimitry Andric 
18060b57cec5SDimitry Andric       EVT FromType = cast<VTSDNode>(V.getOperand(1))->getVT();
18070b57cec5SDimitry Andric       const unsigned NumValidBits = FromType.getSizeInBits();
18080b57cec5SDimitry Andric       for (unsigned i = 0; i < NumValidBits; ++i)
18090b57cec5SDimitry Andric         Bits[i] = (*LHSBits)[i];
18100b57cec5SDimitry Andric 
1811480093f4SDimitry Andric       // These bits are known to be zero but the AssertZext may be from a value
1812480093f4SDimitry Andric       // that already has some constant zero bits (i.e. from a masking and).
18130b57cec5SDimitry Andric       for (unsigned i = NumValidBits; i < NumBits; ++i)
1814480093f4SDimitry Andric         Bits[i] = (*LHSBits)[i].hasValue()
1815480093f4SDimitry Andric                       ? ValueBit((*LHSBits)[i].getValue(),
18160b57cec5SDimitry Andric                                  (*LHSBits)[i].getValueBitIndex(),
1817480093f4SDimitry Andric                                  ValueBit::VariableKnownToBeZero)
1818480093f4SDimitry Andric                       : ValueBit(ValueBit::ConstZero);
18190b57cec5SDimitry Andric 
18200b57cec5SDimitry Andric       return std::make_pair(Interesting, &Bits);
18210b57cec5SDimitry Andric     }
18220b57cec5SDimitry Andric     case ISD::LOAD:
18230b57cec5SDimitry Andric       LoadSDNode *LD = cast<LoadSDNode>(V);
18240b57cec5SDimitry Andric       if (ISD::isZEXTLoad(V.getNode()) && V.getResNo() == 0) {
18250b57cec5SDimitry Andric         EVT VT = LD->getMemoryVT();
18260b57cec5SDimitry Andric         const unsigned NumValidBits = VT.getSizeInBits();
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric         for (unsigned i = 0; i < NumValidBits; ++i)
18290b57cec5SDimitry Andric           Bits[i] = ValueBit(V, i);
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric         // These bits are known to be zero.
18320b57cec5SDimitry Andric         for (unsigned i = NumValidBits; i < NumBits; ++i)
18330b57cec5SDimitry Andric           Bits[i] = ValueBit(V, i, ValueBit::VariableKnownToBeZero);
18340b57cec5SDimitry Andric 
18350b57cec5SDimitry Andric         // Zero-extending load itself cannot be optimized. So, it is not
18360b57cec5SDimitry Andric         // interesting by itself though it gives useful information.
18370b57cec5SDimitry Andric         return std::make_pair(Interesting = false, &Bits);
18380b57cec5SDimitry Andric       }
18390b57cec5SDimitry Andric       break;
18400b57cec5SDimitry Andric     }
18410b57cec5SDimitry Andric 
18420b57cec5SDimitry Andric     for (unsigned i = 0; i < NumBits; ++i)
18430b57cec5SDimitry Andric       Bits[i] = ValueBit(V, i);
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric     return std::make_pair(Interesting = false, &Bits);
18460b57cec5SDimitry Andric   }
18470b57cec5SDimitry Andric 
18480b57cec5SDimitry Andric   // For each value (except the constant ones), compute the left-rotate amount
18490b57cec5SDimitry Andric   // to get it from its original to final position.
computeRotationAmounts()18500b57cec5SDimitry Andric   void computeRotationAmounts() {
18510b57cec5SDimitry Andric     NeedMask = false;
18520b57cec5SDimitry Andric     RLAmt.resize(Bits.size());
18530b57cec5SDimitry Andric     for (unsigned i = 0; i < Bits.size(); ++i)
18540b57cec5SDimitry Andric       if (Bits[i].hasValue()) {
18550b57cec5SDimitry Andric         unsigned VBI = Bits[i].getValueBitIndex();
18560b57cec5SDimitry Andric         if (i >= VBI)
18570b57cec5SDimitry Andric           RLAmt[i] = i - VBI;
18580b57cec5SDimitry Andric         else
18590b57cec5SDimitry Andric           RLAmt[i] = Bits.size() - (VBI - i);
18600b57cec5SDimitry Andric       } else if (Bits[i].isZero()) {
18610b57cec5SDimitry Andric         NeedMask = true;
18620b57cec5SDimitry Andric         RLAmt[i] = UINT32_MAX;
18630b57cec5SDimitry Andric       } else {
18640b57cec5SDimitry Andric         llvm_unreachable("Unknown value bit type");
18650b57cec5SDimitry Andric       }
18660b57cec5SDimitry Andric   }
18670b57cec5SDimitry Andric 
18680b57cec5SDimitry Andric   // Collect groups of consecutive bits with the same underlying value and
18690b57cec5SDimitry Andric   // rotation factor. If we're doing late masking, we ignore zeros, otherwise
18700b57cec5SDimitry Andric   // they break up groups.
collectBitGroups(bool LateMask)18710b57cec5SDimitry Andric   void collectBitGroups(bool LateMask) {
18720b57cec5SDimitry Andric     BitGroups.clear();
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric     unsigned LastRLAmt = RLAmt[0];
18750b57cec5SDimitry Andric     SDValue LastValue = Bits[0].hasValue() ? Bits[0].getValue() : SDValue();
18760b57cec5SDimitry Andric     unsigned LastGroupStartIdx = 0;
18770b57cec5SDimitry Andric     bool IsGroupOfZeros = !Bits[LastGroupStartIdx].hasValue();
18780b57cec5SDimitry Andric     for (unsigned i = 1; i < Bits.size(); ++i) {
18790b57cec5SDimitry Andric       unsigned ThisRLAmt = RLAmt[i];
18800b57cec5SDimitry Andric       SDValue ThisValue = Bits[i].hasValue() ? Bits[i].getValue() : SDValue();
18810b57cec5SDimitry Andric       if (LateMask && !ThisValue) {
18820b57cec5SDimitry Andric         ThisValue = LastValue;
18830b57cec5SDimitry Andric         ThisRLAmt = LastRLAmt;
18840b57cec5SDimitry Andric         // If we're doing late masking, then the first bit group always starts
18850b57cec5SDimitry Andric         // at zero (even if the first bits were zero).
18860b57cec5SDimitry Andric         if (BitGroups.empty())
18870b57cec5SDimitry Andric           LastGroupStartIdx = 0;
18880b57cec5SDimitry Andric       }
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric       // If this bit is known to be zero and the current group is a bit group
18910b57cec5SDimitry Andric       // of zeros, we do not need to terminate the current bit group even the
18920b57cec5SDimitry Andric       // Value or RLAmt does not match here. Instead, we terminate this group
18930b57cec5SDimitry Andric       // when the first non-zero bit appears later.
18940b57cec5SDimitry Andric       if (IsGroupOfZeros && Bits[i].isZero())
18950b57cec5SDimitry Andric         continue;
18960b57cec5SDimitry Andric 
18970b57cec5SDimitry Andric       // If this bit has the same underlying value and the same rotate factor as
18980b57cec5SDimitry Andric       // the last one, then they're part of the same group.
18990b57cec5SDimitry Andric       if (ThisRLAmt == LastRLAmt && ThisValue == LastValue)
19000b57cec5SDimitry Andric         // We cannot continue the current group if this bits is not known to
19010b57cec5SDimitry Andric         // be zero in a bit group of zeros.
19020b57cec5SDimitry Andric         if (!(IsGroupOfZeros && ThisValue && !Bits[i].isZero()))
19030b57cec5SDimitry Andric           continue;
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric       if (LastValue.getNode())
19060b57cec5SDimitry Andric         BitGroups.push_back(BitGroup(LastValue, LastRLAmt, LastGroupStartIdx,
19070b57cec5SDimitry Andric                                      i-1));
19080b57cec5SDimitry Andric       LastRLAmt = ThisRLAmt;
19090b57cec5SDimitry Andric       LastValue = ThisValue;
19100b57cec5SDimitry Andric       LastGroupStartIdx = i;
19110b57cec5SDimitry Andric       IsGroupOfZeros = !Bits[LastGroupStartIdx].hasValue();
19120b57cec5SDimitry Andric     }
19130b57cec5SDimitry Andric     if (LastValue.getNode())
19140b57cec5SDimitry Andric       BitGroups.push_back(BitGroup(LastValue, LastRLAmt, LastGroupStartIdx,
19150b57cec5SDimitry Andric                                    Bits.size()-1));
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric     if (BitGroups.empty())
19180b57cec5SDimitry Andric       return;
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric     // We might be able to combine the first and last groups.
19210b57cec5SDimitry Andric     if (BitGroups.size() > 1) {
19220b57cec5SDimitry Andric       // If the first and last groups are the same, then remove the first group
19230b57cec5SDimitry Andric       // in favor of the last group, making the ending index of the last group
19240b57cec5SDimitry Andric       // equal to the ending index of the to-be-removed first group.
19250b57cec5SDimitry Andric       if (BitGroups[0].StartIdx == 0 &&
19260b57cec5SDimitry Andric           BitGroups[BitGroups.size()-1].EndIdx == Bits.size()-1 &&
19270b57cec5SDimitry Andric           BitGroups[0].V == BitGroups[BitGroups.size()-1].V &&
19280b57cec5SDimitry Andric           BitGroups[0].RLAmt == BitGroups[BitGroups.size()-1].RLAmt) {
19290b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "\tcombining final bit group with initial one\n");
19300b57cec5SDimitry Andric         BitGroups[BitGroups.size()-1].EndIdx = BitGroups[0].EndIdx;
19310b57cec5SDimitry Andric         BitGroups.erase(BitGroups.begin());
19320b57cec5SDimitry Andric       }
19330b57cec5SDimitry Andric     }
19340b57cec5SDimitry Andric   }
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric   // Take all (SDValue, RLAmt) pairs and sort them by the number of groups
19370b57cec5SDimitry Andric   // associated with each. If the number of groups are same, we prefer a group
19380b57cec5SDimitry Andric   // which does not require rotate, i.e. RLAmt is 0, to avoid the first rotate
19390b57cec5SDimitry Andric   // instruction. If there is a degeneracy, pick the one that occurs
19400b57cec5SDimitry Andric   // first (in the final value).
collectValueRotInfo()19410b57cec5SDimitry Andric   void collectValueRotInfo() {
19420b57cec5SDimitry Andric     ValueRots.clear();
19430b57cec5SDimitry Andric 
19440b57cec5SDimitry Andric     for (auto &BG : BitGroups) {
19450b57cec5SDimitry Andric       unsigned RLAmtKey = BG.RLAmt + (BG.Repl32 ? 64 : 0);
19460b57cec5SDimitry Andric       ValueRotInfo &VRI = ValueRots[std::make_pair(BG.V, RLAmtKey)];
19470b57cec5SDimitry Andric       VRI.V = BG.V;
19480b57cec5SDimitry Andric       VRI.RLAmt = BG.RLAmt;
19490b57cec5SDimitry Andric       VRI.Repl32 = BG.Repl32;
19500b57cec5SDimitry Andric       VRI.NumGroups += 1;
19510b57cec5SDimitry Andric       VRI.FirstGroupStartIdx = std::min(VRI.FirstGroupStartIdx, BG.StartIdx);
19520b57cec5SDimitry Andric     }
19530b57cec5SDimitry Andric 
19540b57cec5SDimitry Andric     // Now that we've collected the various ValueRotInfo instances, we need to
19550b57cec5SDimitry Andric     // sort them.
19560b57cec5SDimitry Andric     ValueRotsVec.clear();
19570b57cec5SDimitry Andric     for (auto &I : ValueRots) {
19580b57cec5SDimitry Andric       ValueRotsVec.push_back(I.second);
19590b57cec5SDimitry Andric     }
19600b57cec5SDimitry Andric     llvm::sort(ValueRotsVec);
19610b57cec5SDimitry Andric   }
19620b57cec5SDimitry Andric 
19630b57cec5SDimitry Andric   // In 64-bit mode, rlwinm and friends have a rotation operator that
19640b57cec5SDimitry Andric   // replicates the low-order 32 bits into the high-order 32-bits. The mask
19650b57cec5SDimitry Andric   // indices of these instructions can only be in the lower 32 bits, so they
19660b57cec5SDimitry Andric   // can only represent some 64-bit bit groups. However, when they can be used,
19670b57cec5SDimitry Andric   // the 32-bit replication can be used to represent, as a single bit group,
19680b57cec5SDimitry Andric   // otherwise separate bit groups. We'll convert to replicated-32-bit bit
19690b57cec5SDimitry Andric   // groups when possible. Returns true if any of the bit groups were
19700b57cec5SDimitry Andric   // converted.
assignRepl32BitGroups()19710b57cec5SDimitry Andric   void assignRepl32BitGroups() {
19720b57cec5SDimitry Andric     // If we have bits like this:
19730b57cec5SDimitry Andric     //
19740b57cec5SDimitry Andric     // Indices:    15 14 13 12 11 10 9 8  7  6  5  4  3  2  1  0
19750b57cec5SDimitry Andric     // V bits: ... 7  6  5  4  3  2  1 0 31 30 29 28 27 26 25 24
19760b57cec5SDimitry Andric     // Groups:    |      RLAmt = 8      |      RLAmt = 40       |
19770b57cec5SDimitry Andric     //
19780b57cec5SDimitry Andric     // But, making use of a 32-bit operation that replicates the low-order 32
19790b57cec5SDimitry Andric     // bits into the high-order 32 bits, this can be one bit group with a RLAmt
19800b57cec5SDimitry Andric     // of 8.
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric     auto IsAllLow32 = [this](BitGroup & BG) {
19830b57cec5SDimitry Andric       if (BG.StartIdx <= BG.EndIdx) {
19840b57cec5SDimitry Andric         for (unsigned i = BG.StartIdx; i <= BG.EndIdx; ++i) {
19850b57cec5SDimitry Andric           if (!Bits[i].hasValue())
19860b57cec5SDimitry Andric             continue;
19870b57cec5SDimitry Andric           if (Bits[i].getValueBitIndex() >= 32)
19880b57cec5SDimitry Andric             return false;
19890b57cec5SDimitry Andric         }
19900b57cec5SDimitry Andric       } else {
19910b57cec5SDimitry Andric         for (unsigned i = BG.StartIdx; i < Bits.size(); ++i) {
19920b57cec5SDimitry Andric           if (!Bits[i].hasValue())
19930b57cec5SDimitry Andric             continue;
19940b57cec5SDimitry Andric           if (Bits[i].getValueBitIndex() >= 32)
19950b57cec5SDimitry Andric             return false;
19960b57cec5SDimitry Andric         }
19970b57cec5SDimitry Andric         for (unsigned i = 0; i <= BG.EndIdx; ++i) {
19980b57cec5SDimitry Andric           if (!Bits[i].hasValue())
19990b57cec5SDimitry Andric             continue;
20000b57cec5SDimitry Andric           if (Bits[i].getValueBitIndex() >= 32)
20010b57cec5SDimitry Andric             return false;
20020b57cec5SDimitry Andric         }
20030b57cec5SDimitry Andric       }
20040b57cec5SDimitry Andric 
20050b57cec5SDimitry Andric       return true;
20060b57cec5SDimitry Andric     };
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric     for (auto &BG : BitGroups) {
20090b57cec5SDimitry Andric       // If this bit group has RLAmt of 0 and will not be merged with
20100b57cec5SDimitry Andric       // another bit group, we don't benefit from Repl32. We don't mark
20110b57cec5SDimitry Andric       // such group to give more freedom for later instruction selection.
20120b57cec5SDimitry Andric       if (BG.RLAmt == 0) {
20130b57cec5SDimitry Andric         auto PotentiallyMerged = [this](BitGroup & BG) {
20140b57cec5SDimitry Andric           for (auto &BG2 : BitGroups)
20150b57cec5SDimitry Andric             if (&BG != &BG2 && BG.V == BG2.V &&
20160b57cec5SDimitry Andric                 (BG2.RLAmt == 0 || BG2.RLAmt == 32))
20170b57cec5SDimitry Andric               return true;
20180b57cec5SDimitry Andric           return false;
20190b57cec5SDimitry Andric         };
20200b57cec5SDimitry Andric         if (!PotentiallyMerged(BG))
20210b57cec5SDimitry Andric           continue;
20220b57cec5SDimitry Andric       }
20230b57cec5SDimitry Andric       if (BG.StartIdx < 32 && BG.EndIdx < 32) {
20240b57cec5SDimitry Andric         if (IsAllLow32(BG)) {
20250b57cec5SDimitry Andric           if (BG.RLAmt >= 32) {
20260b57cec5SDimitry Andric             BG.RLAmt -= 32;
20270b57cec5SDimitry Andric             BG.Repl32CR = true;
20280b57cec5SDimitry Andric           }
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric           BG.Repl32 = true;
20310b57cec5SDimitry Andric 
20320b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "\t32-bit replicated bit group for "
20330b57cec5SDimitry Andric                             << BG.V.getNode() << " RLAmt = " << BG.RLAmt << " ["
20340b57cec5SDimitry Andric                             << BG.StartIdx << ", " << BG.EndIdx << "]\n");
20350b57cec5SDimitry Andric         }
20360b57cec5SDimitry Andric       }
20370b57cec5SDimitry Andric     }
20380b57cec5SDimitry Andric 
20390b57cec5SDimitry Andric     // Now walk through the bit groups, consolidating where possible.
20400b57cec5SDimitry Andric     for (auto I = BitGroups.begin(); I != BitGroups.end();) {
20410b57cec5SDimitry Andric       // We might want to remove this bit group by merging it with the previous
20420b57cec5SDimitry Andric       // group (which might be the ending group).
20430b57cec5SDimitry Andric       auto IP = (I == BitGroups.begin()) ?
20440b57cec5SDimitry Andric                 std::prev(BitGroups.end()) : std::prev(I);
20450b57cec5SDimitry Andric       if (I->Repl32 && IP->Repl32 && I->V == IP->V && I->RLAmt == IP->RLAmt &&
20460b57cec5SDimitry Andric           I->StartIdx == (IP->EndIdx + 1) % 64 && I != IP) {
20470b57cec5SDimitry Andric 
20480b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "\tcombining 32-bit replicated bit group for "
20490b57cec5SDimitry Andric                           << I->V.getNode() << " RLAmt = " << I->RLAmt << " ["
20500b57cec5SDimitry Andric                           << I->StartIdx << ", " << I->EndIdx
20510b57cec5SDimitry Andric                           << "] with group with range [" << IP->StartIdx << ", "
20520b57cec5SDimitry Andric                           << IP->EndIdx << "]\n");
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric         IP->EndIdx = I->EndIdx;
20550b57cec5SDimitry Andric         IP->Repl32CR = IP->Repl32CR || I->Repl32CR;
20560b57cec5SDimitry Andric         IP->Repl32Coalesced = true;
20570b57cec5SDimitry Andric         I = BitGroups.erase(I);
20580b57cec5SDimitry Andric         continue;
20590b57cec5SDimitry Andric       } else {
20600b57cec5SDimitry Andric         // There is a special case worth handling: If there is a single group
20610b57cec5SDimitry Andric         // covering the entire upper 32 bits, and it can be merged with both
20620b57cec5SDimitry Andric         // the next and previous groups (which might be the same group), then
20630b57cec5SDimitry Andric         // do so. If it is the same group (so there will be only one group in
20640b57cec5SDimitry Andric         // total), then we need to reverse the order of the range so that it
20650b57cec5SDimitry Andric         // covers the entire 64 bits.
20660b57cec5SDimitry Andric         if (I->StartIdx == 32 && I->EndIdx == 63) {
20670b57cec5SDimitry Andric           assert(std::next(I) == BitGroups.end() &&
20680b57cec5SDimitry Andric                  "bit group ends at index 63 but there is another?");
20690b57cec5SDimitry Andric           auto IN = BitGroups.begin();
20700b57cec5SDimitry Andric 
20710b57cec5SDimitry Andric           if (IP->Repl32 && IN->Repl32 && I->V == IP->V && I->V == IN->V &&
20720b57cec5SDimitry Andric               (I->RLAmt % 32) == IP->RLAmt && (I->RLAmt % 32) == IN->RLAmt &&
20730b57cec5SDimitry Andric               IP->EndIdx == 31 && IN->StartIdx == 0 && I != IP &&
20740b57cec5SDimitry Andric               IsAllLow32(*I)) {
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric             LLVM_DEBUG(dbgs() << "\tcombining bit group for " << I->V.getNode()
20770b57cec5SDimitry Andric                               << " RLAmt = " << I->RLAmt << " [" << I->StartIdx
20780b57cec5SDimitry Andric                               << ", " << I->EndIdx
20790b57cec5SDimitry Andric                               << "] with 32-bit replicated groups with ranges ["
20800b57cec5SDimitry Andric                               << IP->StartIdx << ", " << IP->EndIdx << "] and ["
20810b57cec5SDimitry Andric                               << IN->StartIdx << ", " << IN->EndIdx << "]\n");
20820b57cec5SDimitry Andric 
20830b57cec5SDimitry Andric             if (IP == IN) {
20840b57cec5SDimitry Andric               // There is only one other group; change it to cover the whole
20850b57cec5SDimitry Andric               // range (backward, so that it can still be Repl32 but cover the
20860b57cec5SDimitry Andric               // whole 64-bit range).
20870b57cec5SDimitry Andric               IP->StartIdx = 31;
20880b57cec5SDimitry Andric               IP->EndIdx = 30;
20890b57cec5SDimitry Andric               IP->Repl32CR = IP->Repl32CR || I->RLAmt >= 32;
20900b57cec5SDimitry Andric               IP->Repl32Coalesced = true;
20910b57cec5SDimitry Andric               I = BitGroups.erase(I);
20920b57cec5SDimitry Andric             } else {
20930b57cec5SDimitry Andric               // There are two separate groups, one before this group and one
20940b57cec5SDimitry Andric               // after us (at the beginning). We're going to remove this group,
20950b57cec5SDimitry Andric               // but also the group at the very beginning.
20960b57cec5SDimitry Andric               IP->EndIdx = IN->EndIdx;
20970b57cec5SDimitry Andric               IP->Repl32CR = IP->Repl32CR || IN->Repl32CR || I->RLAmt >= 32;
20980b57cec5SDimitry Andric               IP->Repl32Coalesced = true;
20990b57cec5SDimitry Andric               I = BitGroups.erase(I);
21000b57cec5SDimitry Andric               BitGroups.erase(BitGroups.begin());
21010b57cec5SDimitry Andric             }
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric             // This must be the last group in the vector (and we might have
21040b57cec5SDimitry Andric             // just invalidated the iterator above), so break here.
21050b57cec5SDimitry Andric             break;
21060b57cec5SDimitry Andric           }
21070b57cec5SDimitry Andric         }
21080b57cec5SDimitry Andric       }
21090b57cec5SDimitry Andric 
21100b57cec5SDimitry Andric       ++I;
21110b57cec5SDimitry Andric     }
21120b57cec5SDimitry Andric   }
21130b57cec5SDimitry Andric 
getI32Imm(unsigned Imm,const SDLoc & dl)21140b57cec5SDimitry Andric   SDValue getI32Imm(unsigned Imm, const SDLoc &dl) {
21150b57cec5SDimitry Andric     return CurDAG->getTargetConstant(Imm, dl, MVT::i32);
21160b57cec5SDimitry Andric   }
21170b57cec5SDimitry Andric 
getZerosMask()21180b57cec5SDimitry Andric   uint64_t getZerosMask() {
21190b57cec5SDimitry Andric     uint64_t Mask = 0;
21200b57cec5SDimitry Andric     for (unsigned i = 0; i < Bits.size(); ++i) {
21210b57cec5SDimitry Andric       if (Bits[i].hasValue())
21220b57cec5SDimitry Andric         continue;
21230b57cec5SDimitry Andric       Mask |= (UINT64_C(1) << i);
21240b57cec5SDimitry Andric     }
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric     return ~Mask;
21270b57cec5SDimitry Andric   }
21280b57cec5SDimitry Andric 
21290b57cec5SDimitry Andric   // This method extends an input value to 64 bit if input is 32-bit integer.
21300b57cec5SDimitry Andric   // While selecting instructions in BitPermutationSelector in 64-bit mode,
21310b57cec5SDimitry Andric   // an input value can be a 32-bit integer if a ZERO_EXTEND node is included.
21320b57cec5SDimitry Andric   // In such case, we extend it to 64 bit to be consistent with other values.
ExtendToInt64(SDValue V,const SDLoc & dl)21330b57cec5SDimitry Andric   SDValue ExtendToInt64(SDValue V, const SDLoc &dl) {
21340b57cec5SDimitry Andric     if (V.getValueSizeInBits() == 64)
21350b57cec5SDimitry Andric       return V;
21360b57cec5SDimitry Andric 
21370b57cec5SDimitry Andric     assert(V.getValueSizeInBits() == 32);
21380b57cec5SDimitry Andric     SDValue SubRegIdx = CurDAG->getTargetConstant(PPC::sub_32, dl, MVT::i32);
21390b57cec5SDimitry Andric     SDValue ImDef = SDValue(CurDAG->getMachineNode(PPC::IMPLICIT_DEF, dl,
21400b57cec5SDimitry Andric                                                    MVT::i64), 0);
21410b57cec5SDimitry Andric     SDValue ExtVal = SDValue(CurDAG->getMachineNode(PPC::INSERT_SUBREG, dl,
21420b57cec5SDimitry Andric                                                     MVT::i64, ImDef, V,
21430b57cec5SDimitry Andric                                                     SubRegIdx), 0);
21440b57cec5SDimitry Andric     return ExtVal;
21450b57cec5SDimitry Andric   }
21460b57cec5SDimitry Andric 
TruncateToInt32(SDValue V,const SDLoc & dl)21470b57cec5SDimitry Andric   SDValue TruncateToInt32(SDValue V, const SDLoc &dl) {
21480b57cec5SDimitry Andric     if (V.getValueSizeInBits() == 32)
21490b57cec5SDimitry Andric       return V;
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric     assert(V.getValueSizeInBits() == 64);
21520b57cec5SDimitry Andric     SDValue SubRegIdx = CurDAG->getTargetConstant(PPC::sub_32, dl, MVT::i32);
21530b57cec5SDimitry Andric     SDValue SubVal = SDValue(CurDAG->getMachineNode(PPC::EXTRACT_SUBREG, dl,
21540b57cec5SDimitry Andric                                                     MVT::i32, V, SubRegIdx), 0);
21550b57cec5SDimitry Andric     return SubVal;
21560b57cec5SDimitry Andric   }
21570b57cec5SDimitry Andric 
21580b57cec5SDimitry Andric   // Depending on the number of groups for a particular value, it might be
21590b57cec5SDimitry Andric   // better to rotate, mask explicitly (using andi/andis), and then or the
21600b57cec5SDimitry Andric   // result. Select this part of the result first.
SelectAndParts32(const SDLoc & dl,SDValue & Res,unsigned * InstCnt)21610b57cec5SDimitry Andric   void SelectAndParts32(const SDLoc &dl, SDValue &Res, unsigned *InstCnt) {
21620b57cec5SDimitry Andric     if (BPermRewriterNoMasking)
21630b57cec5SDimitry Andric       return;
21640b57cec5SDimitry Andric 
21650b57cec5SDimitry Andric     for (ValueRotInfo &VRI : ValueRotsVec) {
21660b57cec5SDimitry Andric       unsigned Mask = 0;
21670b57cec5SDimitry Andric       for (unsigned i = 0; i < Bits.size(); ++i) {
21680b57cec5SDimitry Andric         if (!Bits[i].hasValue() || Bits[i].getValue() != VRI.V)
21690b57cec5SDimitry Andric           continue;
21700b57cec5SDimitry Andric         if (RLAmt[i] != VRI.RLAmt)
21710b57cec5SDimitry Andric           continue;
21720b57cec5SDimitry Andric         Mask |= (1u << i);
21730b57cec5SDimitry Andric       }
21740b57cec5SDimitry Andric 
21750b57cec5SDimitry Andric       // Compute the masks for andi/andis that would be necessary.
21760b57cec5SDimitry Andric       unsigned ANDIMask = (Mask & UINT16_MAX), ANDISMask = Mask >> 16;
21770b57cec5SDimitry Andric       assert((ANDIMask != 0 || ANDISMask != 0) &&
21780b57cec5SDimitry Andric              "No set bits in mask for value bit groups");
21790b57cec5SDimitry Andric       bool NeedsRotate = VRI.RLAmt != 0;
21800b57cec5SDimitry Andric 
21810b57cec5SDimitry Andric       // We're trying to minimize the number of instructions. If we have one
21820b57cec5SDimitry Andric       // group, using one of andi/andis can break even.  If we have three
21830b57cec5SDimitry Andric       // groups, we can use both andi and andis and break even (to use both
21840b57cec5SDimitry Andric       // andi and andis we also need to or the results together). We need four
21850b57cec5SDimitry Andric       // groups if we also need to rotate. To use andi/andis we need to do more
21860b57cec5SDimitry Andric       // than break even because rotate-and-mask instructions tend to be easier
21870b57cec5SDimitry Andric       // to schedule.
21880b57cec5SDimitry Andric 
21890b57cec5SDimitry Andric       // FIXME: We've biased here against using andi/andis, which is right for
21900b57cec5SDimitry Andric       // POWER cores, but not optimal everywhere. For example, on the A2,
21910b57cec5SDimitry Andric       // andi/andis have single-cycle latency whereas the rotate-and-mask
21920b57cec5SDimitry Andric       // instructions take two cycles, and it would be better to bias toward
21930b57cec5SDimitry Andric       // andi/andis in break-even cases.
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric       unsigned NumAndInsts = (unsigned) NeedsRotate +
21960b57cec5SDimitry Andric                              (unsigned) (ANDIMask != 0) +
21970b57cec5SDimitry Andric                              (unsigned) (ANDISMask != 0) +
21980b57cec5SDimitry Andric                              (unsigned) (ANDIMask != 0 && ANDISMask != 0) +
21990b57cec5SDimitry Andric                              (unsigned) (bool) Res;
22000b57cec5SDimitry Andric 
22010b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\t\trotation groups for " << VRI.V.getNode()
22020b57cec5SDimitry Andric                         << " RL: " << VRI.RLAmt << ":"
22030b57cec5SDimitry Andric                         << "\n\t\t\tisel using masking: " << NumAndInsts
22040b57cec5SDimitry Andric                         << " using rotates: " << VRI.NumGroups << "\n");
22050b57cec5SDimitry Andric 
22060b57cec5SDimitry Andric       if (NumAndInsts >= VRI.NumGroups)
22070b57cec5SDimitry Andric         continue;
22080b57cec5SDimitry Andric 
22090b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\t\t\t\tusing masking\n");
22100b57cec5SDimitry Andric 
22110b57cec5SDimitry Andric       if (InstCnt) *InstCnt += NumAndInsts;
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric       SDValue VRot;
22140b57cec5SDimitry Andric       if (VRI.RLAmt) {
22150b57cec5SDimitry Andric         SDValue Ops[] =
22160b57cec5SDimitry Andric           { TruncateToInt32(VRI.V, dl), getI32Imm(VRI.RLAmt, dl),
22170b57cec5SDimitry Andric             getI32Imm(0, dl), getI32Imm(31, dl) };
22180b57cec5SDimitry Andric         VRot = SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32,
22190b57cec5SDimitry Andric                                               Ops), 0);
22200b57cec5SDimitry Andric       } else {
22210b57cec5SDimitry Andric         VRot = TruncateToInt32(VRI.V, dl);
22220b57cec5SDimitry Andric       }
22230b57cec5SDimitry Andric 
22240b57cec5SDimitry Andric       SDValue ANDIVal, ANDISVal;
22250b57cec5SDimitry Andric       if (ANDIMask != 0)
2226480093f4SDimitry Andric         ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDI_rec, dl, MVT::i32,
2227480093f4SDimitry Andric                                                  VRot, getI32Imm(ANDIMask, dl)),
2228480093f4SDimitry Andric                           0);
22290b57cec5SDimitry Andric       if (ANDISMask != 0)
2230480093f4SDimitry Andric         ANDISVal =
2231480093f4SDimitry Andric             SDValue(CurDAG->getMachineNode(PPC::ANDIS_rec, dl, MVT::i32, VRot,
2232480093f4SDimitry Andric                                            getI32Imm(ANDISMask, dl)),
2233480093f4SDimitry Andric                     0);
22340b57cec5SDimitry Andric 
22350b57cec5SDimitry Andric       SDValue TotalVal;
22360b57cec5SDimitry Andric       if (!ANDIVal)
22370b57cec5SDimitry Andric         TotalVal = ANDISVal;
22380b57cec5SDimitry Andric       else if (!ANDISVal)
22390b57cec5SDimitry Andric         TotalVal = ANDIVal;
22400b57cec5SDimitry Andric       else
22410b57cec5SDimitry Andric         TotalVal = SDValue(CurDAG->getMachineNode(PPC::OR, dl, MVT::i32,
22420b57cec5SDimitry Andric                              ANDIVal, ANDISVal), 0);
22430b57cec5SDimitry Andric 
22440b57cec5SDimitry Andric       if (!Res)
22450b57cec5SDimitry Andric         Res = TotalVal;
22460b57cec5SDimitry Andric       else
22470b57cec5SDimitry Andric         Res = SDValue(CurDAG->getMachineNode(PPC::OR, dl, MVT::i32,
22480b57cec5SDimitry Andric                         Res, TotalVal), 0);
22490b57cec5SDimitry Andric 
22500b57cec5SDimitry Andric       // Now, remove all groups with this underlying value and rotation
22510b57cec5SDimitry Andric       // factor.
22520b57cec5SDimitry Andric       eraseMatchingBitGroups([VRI](const BitGroup &BG) {
22530b57cec5SDimitry Andric         return BG.V == VRI.V && BG.RLAmt == VRI.RLAmt;
22540b57cec5SDimitry Andric       });
22550b57cec5SDimitry Andric     }
22560b57cec5SDimitry Andric   }
22570b57cec5SDimitry Andric 
22580b57cec5SDimitry Andric   // Instruction selection for the 32-bit case.
Select32(SDNode * N,bool LateMask,unsigned * InstCnt)22590b57cec5SDimitry Andric   SDNode *Select32(SDNode *N, bool LateMask, unsigned *InstCnt) {
22600b57cec5SDimitry Andric     SDLoc dl(N);
22610b57cec5SDimitry Andric     SDValue Res;
22620b57cec5SDimitry Andric 
22630b57cec5SDimitry Andric     if (InstCnt) *InstCnt = 0;
22640b57cec5SDimitry Andric 
22650b57cec5SDimitry Andric     // Take care of cases that should use andi/andis first.
22660b57cec5SDimitry Andric     SelectAndParts32(dl, Res, InstCnt);
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric     // If we've not yet selected a 'starting' instruction, and we have no zeros
22690b57cec5SDimitry Andric     // to fill in, select the (Value, RLAmt) with the highest priority (largest
22700b57cec5SDimitry Andric     // number of groups), and start with this rotated value.
22710b57cec5SDimitry Andric     if ((!NeedMask || LateMask) && !Res) {
22720b57cec5SDimitry Andric       ValueRotInfo &VRI = ValueRotsVec[0];
22730b57cec5SDimitry Andric       if (VRI.RLAmt) {
22740b57cec5SDimitry Andric         if (InstCnt) *InstCnt += 1;
22750b57cec5SDimitry Andric         SDValue Ops[] =
22760b57cec5SDimitry Andric           { TruncateToInt32(VRI.V, dl), getI32Imm(VRI.RLAmt, dl),
22770b57cec5SDimitry Andric             getI32Imm(0, dl), getI32Imm(31, dl) };
22780b57cec5SDimitry Andric         Res = SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops),
22790b57cec5SDimitry Andric                       0);
22800b57cec5SDimitry Andric       } else {
22810b57cec5SDimitry Andric         Res = TruncateToInt32(VRI.V, dl);
22820b57cec5SDimitry Andric       }
22830b57cec5SDimitry Andric 
22840b57cec5SDimitry Andric       // Now, remove all groups with this underlying value and rotation factor.
22850b57cec5SDimitry Andric       eraseMatchingBitGroups([VRI](const BitGroup &BG) {
22860b57cec5SDimitry Andric         return BG.V == VRI.V && BG.RLAmt == VRI.RLAmt;
22870b57cec5SDimitry Andric       });
22880b57cec5SDimitry Andric     }
22890b57cec5SDimitry Andric 
22900b57cec5SDimitry Andric     if (InstCnt) *InstCnt += BitGroups.size();
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric     // Insert the other groups (one at a time).
22930b57cec5SDimitry Andric     for (auto &BG : BitGroups) {
22940b57cec5SDimitry Andric       if (!Res) {
22950b57cec5SDimitry Andric         SDValue Ops[] =
22960b57cec5SDimitry Andric           { TruncateToInt32(BG.V, dl), getI32Imm(BG.RLAmt, dl),
22970b57cec5SDimitry Andric             getI32Imm(Bits.size() - BG.EndIdx - 1, dl),
22980b57cec5SDimitry Andric             getI32Imm(Bits.size() - BG.StartIdx - 1, dl) };
22990b57cec5SDimitry Andric         Res = SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops), 0);
23000b57cec5SDimitry Andric       } else {
23010b57cec5SDimitry Andric         SDValue Ops[] =
23020b57cec5SDimitry Andric           { Res, TruncateToInt32(BG.V, dl), getI32Imm(BG.RLAmt, dl),
23030b57cec5SDimitry Andric               getI32Imm(Bits.size() - BG.EndIdx - 1, dl),
23040b57cec5SDimitry Andric             getI32Imm(Bits.size() - BG.StartIdx - 1, dl) };
23050b57cec5SDimitry Andric         Res = SDValue(CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops), 0);
23060b57cec5SDimitry Andric       }
23070b57cec5SDimitry Andric     }
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric     if (LateMask) {
23100b57cec5SDimitry Andric       unsigned Mask = (unsigned) getZerosMask();
23110b57cec5SDimitry Andric 
23120b57cec5SDimitry Andric       unsigned ANDIMask = (Mask & UINT16_MAX), ANDISMask = Mask >> 16;
23130b57cec5SDimitry Andric       assert((ANDIMask != 0 || ANDISMask != 0) &&
23140b57cec5SDimitry Andric              "No set bits in zeros mask?");
23150b57cec5SDimitry Andric 
23160b57cec5SDimitry Andric       if (InstCnt) *InstCnt += (unsigned) (ANDIMask != 0) +
23170b57cec5SDimitry Andric                                (unsigned) (ANDISMask != 0) +
23180b57cec5SDimitry Andric                                (unsigned) (ANDIMask != 0 && ANDISMask != 0);
23190b57cec5SDimitry Andric 
23200b57cec5SDimitry Andric       SDValue ANDIVal, ANDISVal;
23210b57cec5SDimitry Andric       if (ANDIMask != 0)
2322480093f4SDimitry Andric         ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDI_rec, dl, MVT::i32,
2323480093f4SDimitry Andric                                                  Res, getI32Imm(ANDIMask, dl)),
2324480093f4SDimitry Andric                           0);
23250b57cec5SDimitry Andric       if (ANDISMask != 0)
2326480093f4SDimitry Andric         ANDISVal =
2327480093f4SDimitry Andric             SDValue(CurDAG->getMachineNode(PPC::ANDIS_rec, dl, MVT::i32, Res,
2328480093f4SDimitry Andric                                            getI32Imm(ANDISMask, dl)),
2329480093f4SDimitry Andric                     0);
23300b57cec5SDimitry Andric 
23310b57cec5SDimitry Andric       if (!ANDIVal)
23320b57cec5SDimitry Andric         Res = ANDISVal;
23330b57cec5SDimitry Andric       else if (!ANDISVal)
23340b57cec5SDimitry Andric         Res = ANDIVal;
23350b57cec5SDimitry Andric       else
23360b57cec5SDimitry Andric         Res = SDValue(CurDAG->getMachineNode(PPC::OR, dl, MVT::i32,
23370b57cec5SDimitry Andric                         ANDIVal, ANDISVal), 0);
23380b57cec5SDimitry Andric     }
23390b57cec5SDimitry Andric 
23400b57cec5SDimitry Andric     return Res.getNode();
23410b57cec5SDimitry Andric   }
23420b57cec5SDimitry Andric 
SelectRotMask64Count(unsigned RLAmt,bool Repl32,unsigned MaskStart,unsigned MaskEnd,bool IsIns)23430b57cec5SDimitry Andric   unsigned SelectRotMask64Count(unsigned RLAmt, bool Repl32,
23440b57cec5SDimitry Andric                                 unsigned MaskStart, unsigned MaskEnd,
23450b57cec5SDimitry Andric                                 bool IsIns) {
23460b57cec5SDimitry Andric     // In the notation used by the instructions, 'start' and 'end' are reversed
23470b57cec5SDimitry Andric     // because bits are counted from high to low order.
23480b57cec5SDimitry Andric     unsigned InstMaskStart = 64 - MaskEnd - 1,
23490b57cec5SDimitry Andric              InstMaskEnd   = 64 - MaskStart - 1;
23500b57cec5SDimitry Andric 
23510b57cec5SDimitry Andric     if (Repl32)
23520b57cec5SDimitry Andric       return 1;
23530b57cec5SDimitry Andric 
23540b57cec5SDimitry Andric     if ((!IsIns && (InstMaskEnd == 63 || InstMaskStart == 0)) ||
23550b57cec5SDimitry Andric         InstMaskEnd == 63 - RLAmt)
23560b57cec5SDimitry Andric       return 1;
23570b57cec5SDimitry Andric 
23580b57cec5SDimitry Andric     return 2;
23590b57cec5SDimitry Andric   }
23600b57cec5SDimitry Andric 
23610b57cec5SDimitry Andric   // For 64-bit values, not all combinations of rotates and masks are
23620b57cec5SDimitry Andric   // available. Produce one if it is available.
SelectRotMask64(SDValue V,const SDLoc & dl,unsigned RLAmt,bool Repl32,unsigned MaskStart,unsigned MaskEnd,unsigned * InstCnt=nullptr)23630b57cec5SDimitry Andric   SDValue SelectRotMask64(SDValue V, const SDLoc &dl, unsigned RLAmt,
23640b57cec5SDimitry Andric                           bool Repl32, unsigned MaskStart, unsigned MaskEnd,
23650b57cec5SDimitry Andric                           unsigned *InstCnt = nullptr) {
23660b57cec5SDimitry Andric     // In the notation used by the instructions, 'start' and 'end' are reversed
23670b57cec5SDimitry Andric     // because bits are counted from high to low order.
23680b57cec5SDimitry Andric     unsigned InstMaskStart = 64 - MaskEnd - 1,
23690b57cec5SDimitry Andric              InstMaskEnd   = 64 - MaskStart - 1;
23700b57cec5SDimitry Andric 
23710b57cec5SDimitry Andric     if (InstCnt) *InstCnt += 1;
23720b57cec5SDimitry Andric 
23730b57cec5SDimitry Andric     if (Repl32) {
23740b57cec5SDimitry Andric       // This rotation amount assumes that the lower 32 bits of the quantity
23750b57cec5SDimitry Andric       // are replicated in the high 32 bits by the rotation operator (which is
23760b57cec5SDimitry Andric       // done by rlwinm and friends).
23770b57cec5SDimitry Andric       assert(InstMaskStart >= 32 && "Mask cannot start out of range");
23780b57cec5SDimitry Andric       assert(InstMaskEnd   >= 32 && "Mask cannot end out of range");
23790b57cec5SDimitry Andric       SDValue Ops[] =
23800b57cec5SDimitry Andric         { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
23810b57cec5SDimitry Andric           getI32Imm(InstMaskStart - 32, dl), getI32Imm(InstMaskEnd - 32, dl) };
23820b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLWINM8, dl, MVT::i64,
23830b57cec5SDimitry Andric                                             Ops), 0);
23840b57cec5SDimitry Andric     }
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric     if (InstMaskEnd == 63) {
23870b57cec5SDimitry Andric       SDValue Ops[] =
23880b57cec5SDimitry Andric         { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
23890b57cec5SDimitry Andric           getI32Imm(InstMaskStart, dl) };
23900b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Ops), 0);
23910b57cec5SDimitry Andric     }
23920b57cec5SDimitry Andric 
23930b57cec5SDimitry Andric     if (InstMaskStart == 0) {
23940b57cec5SDimitry Andric       SDValue Ops[] =
23950b57cec5SDimitry Andric         { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
23960b57cec5SDimitry Andric           getI32Imm(InstMaskEnd, dl) };
23970b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Ops), 0);
23980b57cec5SDimitry Andric     }
23990b57cec5SDimitry Andric 
24000b57cec5SDimitry Andric     if (InstMaskEnd == 63 - RLAmt) {
24010b57cec5SDimitry Andric       SDValue Ops[] =
24020b57cec5SDimitry Andric         { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
24030b57cec5SDimitry Andric           getI32Imm(InstMaskStart, dl) };
24040b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, Ops), 0);
24050b57cec5SDimitry Andric     }
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric     // We cannot do this with a single instruction, so we'll use two. The
24080b57cec5SDimitry Andric     // problem is that we're not free to choose both a rotation amount and mask
24090b57cec5SDimitry Andric     // start and end independently. We can choose an arbitrary mask start and
24100b57cec5SDimitry Andric     // end, but then the rotation amount is fixed. Rotation, however, can be
24110b57cec5SDimitry Andric     // inverted, and so by applying an "inverse" rotation first, we can get the
24120b57cec5SDimitry Andric     // desired result.
24130b57cec5SDimitry Andric     if (InstCnt) *InstCnt += 1;
24140b57cec5SDimitry Andric 
24150b57cec5SDimitry Andric     // The rotation mask for the second instruction must be MaskStart.
24160b57cec5SDimitry Andric     unsigned RLAmt2 = MaskStart;
24170b57cec5SDimitry Andric     // The first instruction must rotate V so that the overall rotation amount
24180b57cec5SDimitry Andric     // is RLAmt.
24190b57cec5SDimitry Andric     unsigned RLAmt1 = (64 + RLAmt - RLAmt2) % 64;
24200b57cec5SDimitry Andric     if (RLAmt1)
24210b57cec5SDimitry Andric       V = SelectRotMask64(V, dl, RLAmt1, false, 0, 63);
24220b57cec5SDimitry Andric     return SelectRotMask64(V, dl, RLAmt2, false, MaskStart, MaskEnd);
24230b57cec5SDimitry Andric   }
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric   // For 64-bit values, not all combinations of rotates and masks are
24260b57cec5SDimitry Andric   // available. Produce a rotate-mask-and-insert if one is available.
SelectRotMaskIns64(SDValue Base,SDValue V,const SDLoc & dl,unsigned RLAmt,bool Repl32,unsigned MaskStart,unsigned MaskEnd,unsigned * InstCnt=nullptr)24270b57cec5SDimitry Andric   SDValue SelectRotMaskIns64(SDValue Base, SDValue V, const SDLoc &dl,
24280b57cec5SDimitry Andric                              unsigned RLAmt, bool Repl32, unsigned MaskStart,
24290b57cec5SDimitry Andric                              unsigned MaskEnd, unsigned *InstCnt = nullptr) {
24300b57cec5SDimitry Andric     // In the notation used by the instructions, 'start' and 'end' are reversed
24310b57cec5SDimitry Andric     // because bits are counted from high to low order.
24320b57cec5SDimitry Andric     unsigned InstMaskStart = 64 - MaskEnd - 1,
24330b57cec5SDimitry Andric              InstMaskEnd   = 64 - MaskStart - 1;
24340b57cec5SDimitry Andric 
24350b57cec5SDimitry Andric     if (InstCnt) *InstCnt += 1;
24360b57cec5SDimitry Andric 
24370b57cec5SDimitry Andric     if (Repl32) {
24380b57cec5SDimitry Andric       // This rotation amount assumes that the lower 32 bits of the quantity
24390b57cec5SDimitry Andric       // are replicated in the high 32 bits by the rotation operator (which is
24400b57cec5SDimitry Andric       // done by rlwinm and friends).
24410b57cec5SDimitry Andric       assert(InstMaskStart >= 32 && "Mask cannot start out of range");
24420b57cec5SDimitry Andric       assert(InstMaskEnd   >= 32 && "Mask cannot end out of range");
24430b57cec5SDimitry Andric       SDValue Ops[] =
24440b57cec5SDimitry Andric         { ExtendToInt64(Base, dl), ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
24450b57cec5SDimitry Andric           getI32Imm(InstMaskStart - 32, dl), getI32Imm(InstMaskEnd - 32, dl) };
24460b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64,
24470b57cec5SDimitry Andric                                             Ops), 0);
24480b57cec5SDimitry Andric     }
24490b57cec5SDimitry Andric 
24500b57cec5SDimitry Andric     if (InstMaskEnd == 63 - RLAmt) {
24510b57cec5SDimitry Andric       SDValue Ops[] =
24520b57cec5SDimitry Andric         { ExtendToInt64(Base, dl), ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
24530b57cec5SDimitry Andric           getI32Imm(InstMaskStart, dl) };
24540b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops), 0);
24550b57cec5SDimitry Andric     }
24560b57cec5SDimitry Andric 
24570b57cec5SDimitry Andric     // We cannot do this with a single instruction, so we'll use two. The
24580b57cec5SDimitry Andric     // problem is that we're not free to choose both a rotation amount and mask
24590b57cec5SDimitry Andric     // start and end independently. We can choose an arbitrary mask start and
24600b57cec5SDimitry Andric     // end, but then the rotation amount is fixed. Rotation, however, can be
24610b57cec5SDimitry Andric     // inverted, and so by applying an "inverse" rotation first, we can get the
24620b57cec5SDimitry Andric     // desired result.
24630b57cec5SDimitry Andric     if (InstCnt) *InstCnt += 1;
24640b57cec5SDimitry Andric 
24650b57cec5SDimitry Andric     // The rotation mask for the second instruction must be MaskStart.
24660b57cec5SDimitry Andric     unsigned RLAmt2 = MaskStart;
24670b57cec5SDimitry Andric     // The first instruction must rotate V so that the overall rotation amount
24680b57cec5SDimitry Andric     // is RLAmt.
24690b57cec5SDimitry Andric     unsigned RLAmt1 = (64 + RLAmt - RLAmt2) % 64;
24700b57cec5SDimitry Andric     if (RLAmt1)
24710b57cec5SDimitry Andric       V = SelectRotMask64(V, dl, RLAmt1, false, 0, 63);
24720b57cec5SDimitry Andric     return SelectRotMaskIns64(Base, V, dl, RLAmt2, false, MaskStart, MaskEnd);
24730b57cec5SDimitry Andric   }
24740b57cec5SDimitry Andric 
SelectAndParts64(const SDLoc & dl,SDValue & Res,unsigned * InstCnt)24750b57cec5SDimitry Andric   void SelectAndParts64(const SDLoc &dl, SDValue &Res, unsigned *InstCnt) {
24760b57cec5SDimitry Andric     if (BPermRewriterNoMasking)
24770b57cec5SDimitry Andric       return;
24780b57cec5SDimitry Andric 
24790b57cec5SDimitry Andric     // The idea here is the same as in the 32-bit version, but with additional
24800b57cec5SDimitry Andric     // complications from the fact that Repl32 might be true. Because we
24810b57cec5SDimitry Andric     // aggressively convert bit groups to Repl32 form (which, for small
24820b57cec5SDimitry Andric     // rotation factors, involves no other change), and then coalesce, it might
24830b57cec5SDimitry Andric     // be the case that a single 64-bit masking operation could handle both
24840b57cec5SDimitry Andric     // some Repl32 groups and some non-Repl32 groups. If converting to Repl32
24850b57cec5SDimitry Andric     // form allowed coalescing, then we must use a 32-bit rotaton in order to
24860b57cec5SDimitry Andric     // completely capture the new combined bit group.
24870b57cec5SDimitry Andric 
24880b57cec5SDimitry Andric     for (ValueRotInfo &VRI : ValueRotsVec) {
24890b57cec5SDimitry Andric       uint64_t Mask = 0;
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric       // We need to add to the mask all bits from the associated bit groups.
24920b57cec5SDimitry Andric       // If Repl32 is false, we need to add bits from bit groups that have
24930b57cec5SDimitry Andric       // Repl32 true, but are trivially convertable to Repl32 false. Such a
24940b57cec5SDimitry Andric       // group is trivially convertable if it overlaps only with the lower 32
24950b57cec5SDimitry Andric       // bits, and the group has not been coalesced.
24960b57cec5SDimitry Andric       auto MatchingBG = [VRI](const BitGroup &BG) {
24970b57cec5SDimitry Andric         if (VRI.V != BG.V)
24980b57cec5SDimitry Andric           return false;
24990b57cec5SDimitry Andric 
25000b57cec5SDimitry Andric         unsigned EffRLAmt = BG.RLAmt;
25010b57cec5SDimitry Andric         if (!VRI.Repl32 && BG.Repl32) {
25020b57cec5SDimitry Andric           if (BG.StartIdx < 32 && BG.EndIdx < 32 && BG.StartIdx <= BG.EndIdx &&
25030b57cec5SDimitry Andric               !BG.Repl32Coalesced) {
25040b57cec5SDimitry Andric             if (BG.Repl32CR)
25050b57cec5SDimitry Andric               EffRLAmt += 32;
25060b57cec5SDimitry Andric           } else {
25070b57cec5SDimitry Andric             return false;
25080b57cec5SDimitry Andric           }
25090b57cec5SDimitry Andric         } else if (VRI.Repl32 != BG.Repl32) {
25100b57cec5SDimitry Andric           return false;
25110b57cec5SDimitry Andric         }
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric         return VRI.RLAmt == EffRLAmt;
25140b57cec5SDimitry Andric       };
25150b57cec5SDimitry Andric 
25160b57cec5SDimitry Andric       for (auto &BG : BitGroups) {
25170b57cec5SDimitry Andric         if (!MatchingBG(BG))
25180b57cec5SDimitry Andric           continue;
25190b57cec5SDimitry Andric 
25200b57cec5SDimitry Andric         if (BG.StartIdx <= BG.EndIdx) {
25210b57cec5SDimitry Andric           for (unsigned i = BG.StartIdx; i <= BG.EndIdx; ++i)
25220b57cec5SDimitry Andric             Mask |= (UINT64_C(1) << i);
25230b57cec5SDimitry Andric         } else {
25240b57cec5SDimitry Andric           for (unsigned i = BG.StartIdx; i < Bits.size(); ++i)
25250b57cec5SDimitry Andric             Mask |= (UINT64_C(1) << i);
25260b57cec5SDimitry Andric           for (unsigned i = 0; i <= BG.EndIdx; ++i)
25270b57cec5SDimitry Andric             Mask |= (UINT64_C(1) << i);
25280b57cec5SDimitry Andric         }
25290b57cec5SDimitry Andric       }
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric       // We can use the 32-bit andi/andis technique if the mask does not
25320b57cec5SDimitry Andric       // require any higher-order bits. This can save an instruction compared
25330b57cec5SDimitry Andric       // to always using the general 64-bit technique.
25340b57cec5SDimitry Andric       bool Use32BitInsts = isUInt<32>(Mask);
25350b57cec5SDimitry Andric       // Compute the masks for andi/andis that would be necessary.
25360b57cec5SDimitry Andric       unsigned ANDIMask = (Mask & UINT16_MAX),
25370b57cec5SDimitry Andric                ANDISMask = (Mask >> 16) & UINT16_MAX;
25380b57cec5SDimitry Andric 
25390b57cec5SDimitry Andric       bool NeedsRotate = VRI.RLAmt || (VRI.Repl32 && !isUInt<32>(Mask));
25400b57cec5SDimitry Andric 
25410b57cec5SDimitry Andric       unsigned NumAndInsts = (unsigned) NeedsRotate +
25420b57cec5SDimitry Andric                              (unsigned) (bool) Res;
2543e8d8bef9SDimitry Andric       unsigned NumOfSelectInsts = 0;
2544e8d8bef9SDimitry Andric       selectI64Imm(CurDAG, dl, Mask, &NumOfSelectInsts);
2545e8d8bef9SDimitry Andric       assert(NumOfSelectInsts > 0 && "Failed to select an i64 constant.");
25460b57cec5SDimitry Andric       if (Use32BitInsts)
25470b57cec5SDimitry Andric         NumAndInsts += (unsigned) (ANDIMask != 0) + (unsigned) (ANDISMask != 0) +
25480b57cec5SDimitry Andric                        (unsigned) (ANDIMask != 0 && ANDISMask != 0);
25490b57cec5SDimitry Andric       else
2550e8d8bef9SDimitry Andric         NumAndInsts += NumOfSelectInsts + /* and */ 1;
25510b57cec5SDimitry Andric 
25520b57cec5SDimitry Andric       unsigned NumRLInsts = 0;
25530b57cec5SDimitry Andric       bool FirstBG = true;
25540b57cec5SDimitry Andric       bool MoreBG = false;
25550b57cec5SDimitry Andric       for (auto &BG : BitGroups) {
25560b57cec5SDimitry Andric         if (!MatchingBG(BG)) {
25570b57cec5SDimitry Andric           MoreBG = true;
25580b57cec5SDimitry Andric           continue;
25590b57cec5SDimitry Andric         }
25600b57cec5SDimitry Andric         NumRLInsts +=
25610b57cec5SDimitry Andric           SelectRotMask64Count(BG.RLAmt, BG.Repl32, BG.StartIdx, BG.EndIdx,
25620b57cec5SDimitry Andric                                !FirstBG);
25630b57cec5SDimitry Andric         FirstBG = false;
25640b57cec5SDimitry Andric       }
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\t\trotation groups for " << VRI.V.getNode()
25670b57cec5SDimitry Andric                         << " RL: " << VRI.RLAmt << (VRI.Repl32 ? " (32):" : ":")
25680b57cec5SDimitry Andric                         << "\n\t\t\tisel using masking: " << NumAndInsts
25690b57cec5SDimitry Andric                         << " using rotates: " << NumRLInsts << "\n");
25700b57cec5SDimitry Andric 
25710b57cec5SDimitry Andric       // When we'd use andi/andis, we bias toward using the rotates (andi only
25720b57cec5SDimitry Andric       // has a record form, and is cracked on POWER cores). However, when using
25730b57cec5SDimitry Andric       // general 64-bit constant formation, bias toward the constant form,
25740b57cec5SDimitry Andric       // because that exposes more opportunities for CSE.
25750b57cec5SDimitry Andric       if (NumAndInsts > NumRLInsts)
25760b57cec5SDimitry Andric         continue;
25770b57cec5SDimitry Andric       // When merging multiple bit groups, instruction or is used.
25780b57cec5SDimitry Andric       // But when rotate is used, rldimi can inert the rotated value into any
25790b57cec5SDimitry Andric       // register, so instruction or can be avoided.
25800b57cec5SDimitry Andric       if ((Use32BitInsts || MoreBG) && NumAndInsts == NumRLInsts)
25810b57cec5SDimitry Andric         continue;
25820b57cec5SDimitry Andric 
25830b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\t\t\t\tusing masking\n");
25840b57cec5SDimitry Andric 
25850b57cec5SDimitry Andric       if (InstCnt) *InstCnt += NumAndInsts;
25860b57cec5SDimitry Andric 
25870b57cec5SDimitry Andric       SDValue VRot;
25880b57cec5SDimitry Andric       // We actually need to generate a rotation if we have a non-zero rotation
25890b57cec5SDimitry Andric       // factor or, in the Repl32 case, if we care about any of the
25900b57cec5SDimitry Andric       // higher-order replicated bits. In the latter case, we generate a mask
25910b57cec5SDimitry Andric       // backward so that it actually includes the entire 64 bits.
25920b57cec5SDimitry Andric       if (VRI.RLAmt || (VRI.Repl32 && !isUInt<32>(Mask)))
25930b57cec5SDimitry Andric         VRot = SelectRotMask64(VRI.V, dl, VRI.RLAmt, VRI.Repl32,
25940b57cec5SDimitry Andric                                VRI.Repl32 ? 31 : 0, VRI.Repl32 ? 30 : 63);
25950b57cec5SDimitry Andric       else
25960b57cec5SDimitry Andric         VRot = VRI.V;
25970b57cec5SDimitry Andric 
25980b57cec5SDimitry Andric       SDValue TotalVal;
25990b57cec5SDimitry Andric       if (Use32BitInsts) {
26000b57cec5SDimitry Andric         assert((ANDIMask != 0 || ANDISMask != 0) &&
26010b57cec5SDimitry Andric                "No set bits in mask when using 32-bit ands for 64-bit value");
26020b57cec5SDimitry Andric 
26030b57cec5SDimitry Andric         SDValue ANDIVal, ANDISVal;
26040b57cec5SDimitry Andric         if (ANDIMask != 0)
2605480093f4SDimitry Andric           ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDI8_rec, dl, MVT::i64,
26060b57cec5SDimitry Andric                                                    ExtendToInt64(VRot, dl),
26070b57cec5SDimitry Andric                                                    getI32Imm(ANDIMask, dl)),
26080b57cec5SDimitry Andric                             0);
26090b57cec5SDimitry Andric         if (ANDISMask != 0)
2610480093f4SDimitry Andric           ANDISVal =
2611480093f4SDimitry Andric               SDValue(CurDAG->getMachineNode(PPC::ANDIS8_rec, dl, MVT::i64,
26120b57cec5SDimitry Andric                                              ExtendToInt64(VRot, dl),
26130b57cec5SDimitry Andric                                              getI32Imm(ANDISMask, dl)),
26140b57cec5SDimitry Andric                       0);
26150b57cec5SDimitry Andric 
26160b57cec5SDimitry Andric         if (!ANDIVal)
26170b57cec5SDimitry Andric           TotalVal = ANDISVal;
26180b57cec5SDimitry Andric         else if (!ANDISVal)
26190b57cec5SDimitry Andric           TotalVal = ANDIVal;
26200b57cec5SDimitry Andric         else
26210b57cec5SDimitry Andric           TotalVal = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
26220b57cec5SDimitry Andric                                ExtendToInt64(ANDIVal, dl), ANDISVal), 0);
26230b57cec5SDimitry Andric       } else {
26240b57cec5SDimitry Andric         TotalVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0);
26250b57cec5SDimitry Andric         TotalVal =
26260b57cec5SDimitry Andric           SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
26270b57cec5SDimitry Andric                                          ExtendToInt64(VRot, dl), TotalVal),
26280b57cec5SDimitry Andric                   0);
26290b57cec5SDimitry Andric      }
26300b57cec5SDimitry Andric 
26310b57cec5SDimitry Andric       if (!Res)
26320b57cec5SDimitry Andric         Res = TotalVal;
26330b57cec5SDimitry Andric       else
26340b57cec5SDimitry Andric         Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
26350b57cec5SDimitry Andric                                              ExtendToInt64(Res, dl), TotalVal),
26360b57cec5SDimitry Andric                       0);
26370b57cec5SDimitry Andric 
26380b57cec5SDimitry Andric       // Now, remove all groups with this underlying value and rotation
26390b57cec5SDimitry Andric       // factor.
26400b57cec5SDimitry Andric       eraseMatchingBitGroups(MatchingBG);
26410b57cec5SDimitry Andric     }
26420b57cec5SDimitry Andric   }
26430b57cec5SDimitry Andric 
26440b57cec5SDimitry Andric   // Instruction selection for the 64-bit case.
Select64(SDNode * N,bool LateMask,unsigned * InstCnt)26450b57cec5SDimitry Andric   SDNode *Select64(SDNode *N, bool LateMask, unsigned *InstCnt) {
26460b57cec5SDimitry Andric     SDLoc dl(N);
26470b57cec5SDimitry Andric     SDValue Res;
26480b57cec5SDimitry Andric 
26490b57cec5SDimitry Andric     if (InstCnt) *InstCnt = 0;
26500b57cec5SDimitry Andric 
26510b57cec5SDimitry Andric     // Take care of cases that should use andi/andis first.
26520b57cec5SDimitry Andric     SelectAndParts64(dl, Res, InstCnt);
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric     // If we've not yet selected a 'starting' instruction, and we have no zeros
26550b57cec5SDimitry Andric     // to fill in, select the (Value, RLAmt) with the highest priority (largest
26560b57cec5SDimitry Andric     // number of groups), and start with this rotated value.
26570b57cec5SDimitry Andric     if ((!NeedMask || LateMask) && !Res) {
26580b57cec5SDimitry Andric       // If we have both Repl32 groups and non-Repl32 groups, the non-Repl32
26590b57cec5SDimitry Andric       // groups will come first, and so the VRI representing the largest number
26600b57cec5SDimitry Andric       // of groups might not be first (it might be the first Repl32 groups).
26610b57cec5SDimitry Andric       unsigned MaxGroupsIdx = 0;
26620b57cec5SDimitry Andric       if (!ValueRotsVec[0].Repl32) {
26630b57cec5SDimitry Andric         for (unsigned i = 0, ie = ValueRotsVec.size(); i < ie; ++i)
26640b57cec5SDimitry Andric           if (ValueRotsVec[i].Repl32) {
26650b57cec5SDimitry Andric             if (ValueRotsVec[i].NumGroups > ValueRotsVec[0].NumGroups)
26660b57cec5SDimitry Andric               MaxGroupsIdx = i;
26670b57cec5SDimitry Andric             break;
26680b57cec5SDimitry Andric           }
26690b57cec5SDimitry Andric       }
26700b57cec5SDimitry Andric 
26710b57cec5SDimitry Andric       ValueRotInfo &VRI = ValueRotsVec[MaxGroupsIdx];
26720b57cec5SDimitry Andric       bool NeedsRotate = false;
26730b57cec5SDimitry Andric       if (VRI.RLAmt) {
26740b57cec5SDimitry Andric         NeedsRotate = true;
26750b57cec5SDimitry Andric       } else if (VRI.Repl32) {
26760b57cec5SDimitry Andric         for (auto &BG : BitGroups) {
26770b57cec5SDimitry Andric           if (BG.V != VRI.V || BG.RLAmt != VRI.RLAmt ||
26780b57cec5SDimitry Andric               BG.Repl32 != VRI.Repl32)
26790b57cec5SDimitry Andric             continue;
26800b57cec5SDimitry Andric 
26810b57cec5SDimitry Andric           // We don't need a rotate if the bit group is confined to the lower
26820b57cec5SDimitry Andric           // 32 bits.
26830b57cec5SDimitry Andric           if (BG.StartIdx < 32 && BG.EndIdx < 32 && BG.StartIdx < BG.EndIdx)
26840b57cec5SDimitry Andric             continue;
26850b57cec5SDimitry Andric 
26860b57cec5SDimitry Andric           NeedsRotate = true;
26870b57cec5SDimitry Andric           break;
26880b57cec5SDimitry Andric         }
26890b57cec5SDimitry Andric       }
26900b57cec5SDimitry Andric 
26910b57cec5SDimitry Andric       if (NeedsRotate)
26920b57cec5SDimitry Andric         Res = SelectRotMask64(VRI.V, dl, VRI.RLAmt, VRI.Repl32,
26930b57cec5SDimitry Andric                               VRI.Repl32 ? 31 : 0, VRI.Repl32 ? 30 : 63,
26940b57cec5SDimitry Andric                               InstCnt);
26950b57cec5SDimitry Andric       else
26960b57cec5SDimitry Andric         Res = VRI.V;
26970b57cec5SDimitry Andric 
26980b57cec5SDimitry Andric       // Now, remove all groups with this underlying value and rotation factor.
26990b57cec5SDimitry Andric       if (Res)
27000b57cec5SDimitry Andric         eraseMatchingBitGroups([VRI](const BitGroup &BG) {
27010b57cec5SDimitry Andric           return BG.V == VRI.V && BG.RLAmt == VRI.RLAmt &&
27020b57cec5SDimitry Andric                  BG.Repl32 == VRI.Repl32;
27030b57cec5SDimitry Andric         });
27040b57cec5SDimitry Andric     }
27050b57cec5SDimitry Andric 
27060b57cec5SDimitry Andric     // Because 64-bit rotates are more flexible than inserts, we might have a
27070b57cec5SDimitry Andric     // preference regarding which one we do first (to save one instruction).
27080b57cec5SDimitry Andric     if (!Res)
27090b57cec5SDimitry Andric       for (auto I = BitGroups.begin(), IE = BitGroups.end(); I != IE; ++I) {
27100b57cec5SDimitry Andric         if (SelectRotMask64Count(I->RLAmt, I->Repl32, I->StartIdx, I->EndIdx,
27110b57cec5SDimitry Andric                                 false) <
27120b57cec5SDimitry Andric             SelectRotMask64Count(I->RLAmt, I->Repl32, I->StartIdx, I->EndIdx,
27130b57cec5SDimitry Andric                                 true)) {
27140b57cec5SDimitry Andric           if (I != BitGroups.begin()) {
27150b57cec5SDimitry Andric             BitGroup BG = *I;
27160b57cec5SDimitry Andric             BitGroups.erase(I);
27170b57cec5SDimitry Andric             BitGroups.insert(BitGroups.begin(), BG);
27180b57cec5SDimitry Andric           }
27190b57cec5SDimitry Andric 
27200b57cec5SDimitry Andric           break;
27210b57cec5SDimitry Andric         }
27220b57cec5SDimitry Andric       }
27230b57cec5SDimitry Andric 
27240b57cec5SDimitry Andric     // Insert the other groups (one at a time).
27250b57cec5SDimitry Andric     for (auto &BG : BitGroups) {
27260b57cec5SDimitry Andric       if (!Res)
27270b57cec5SDimitry Andric         Res = SelectRotMask64(BG.V, dl, BG.RLAmt, BG.Repl32, BG.StartIdx,
27280b57cec5SDimitry Andric                               BG.EndIdx, InstCnt);
27290b57cec5SDimitry Andric       else
27300b57cec5SDimitry Andric         Res = SelectRotMaskIns64(Res, BG.V, dl, BG.RLAmt, BG.Repl32,
27310b57cec5SDimitry Andric                                  BG.StartIdx, BG.EndIdx, InstCnt);
27320b57cec5SDimitry Andric     }
27330b57cec5SDimitry Andric 
27340b57cec5SDimitry Andric     if (LateMask) {
27350b57cec5SDimitry Andric       uint64_t Mask = getZerosMask();
27360b57cec5SDimitry Andric 
27370b57cec5SDimitry Andric       // We can use the 32-bit andi/andis technique if the mask does not
27380b57cec5SDimitry Andric       // require any higher-order bits. This can save an instruction compared
27390b57cec5SDimitry Andric       // to always using the general 64-bit technique.
27400b57cec5SDimitry Andric       bool Use32BitInsts = isUInt<32>(Mask);
27410b57cec5SDimitry Andric       // Compute the masks for andi/andis that would be necessary.
27420b57cec5SDimitry Andric       unsigned ANDIMask = (Mask & UINT16_MAX),
27430b57cec5SDimitry Andric                ANDISMask = (Mask >> 16) & UINT16_MAX;
27440b57cec5SDimitry Andric 
27450b57cec5SDimitry Andric       if (Use32BitInsts) {
27460b57cec5SDimitry Andric         assert((ANDIMask != 0 || ANDISMask != 0) &&
27470b57cec5SDimitry Andric                "No set bits in mask when using 32-bit ands for 64-bit value");
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric         if (InstCnt) *InstCnt += (unsigned) (ANDIMask != 0) +
27500b57cec5SDimitry Andric                                  (unsigned) (ANDISMask != 0) +
27510b57cec5SDimitry Andric                                  (unsigned) (ANDIMask != 0 && ANDISMask != 0);
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric         SDValue ANDIVal, ANDISVal;
27540b57cec5SDimitry Andric         if (ANDIMask != 0)
2755480093f4SDimitry Andric           ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDI8_rec, dl, MVT::i64,
2756480093f4SDimitry Andric                                                    ExtendToInt64(Res, dl),
2757480093f4SDimitry Andric                                                    getI32Imm(ANDIMask, dl)),
2758480093f4SDimitry Andric                             0);
27590b57cec5SDimitry Andric         if (ANDISMask != 0)
2760480093f4SDimitry Andric           ANDISVal =
2761480093f4SDimitry Andric               SDValue(CurDAG->getMachineNode(PPC::ANDIS8_rec, dl, MVT::i64,
2762480093f4SDimitry Andric                                              ExtendToInt64(Res, dl),
2763480093f4SDimitry Andric                                              getI32Imm(ANDISMask, dl)),
2764480093f4SDimitry Andric                       0);
27650b57cec5SDimitry Andric 
27660b57cec5SDimitry Andric         if (!ANDIVal)
27670b57cec5SDimitry Andric           Res = ANDISVal;
27680b57cec5SDimitry Andric         else if (!ANDISVal)
27690b57cec5SDimitry Andric           Res = ANDIVal;
27700b57cec5SDimitry Andric         else
27710b57cec5SDimitry Andric           Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
27720b57cec5SDimitry Andric                           ExtendToInt64(ANDIVal, dl), ANDISVal), 0);
27730b57cec5SDimitry Andric       } else {
2774e8d8bef9SDimitry Andric         unsigned NumOfSelectInsts = 0;
2775e8d8bef9SDimitry Andric         SDValue MaskVal =
2776e8d8bef9SDimitry Andric             SDValue(selectI64Imm(CurDAG, dl, Mask, &NumOfSelectInsts), 0);
2777e8d8bef9SDimitry Andric         Res = SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
2778e8d8bef9SDimitry Andric                                              ExtendToInt64(Res, dl), MaskVal),
2779e8d8bef9SDimitry Andric                       0);
2780e8d8bef9SDimitry Andric         if (InstCnt)
2781e8d8bef9SDimitry Andric           *InstCnt += NumOfSelectInsts + /* and */ 1;
27820b57cec5SDimitry Andric       }
27830b57cec5SDimitry Andric     }
27840b57cec5SDimitry Andric 
27850b57cec5SDimitry Andric     return Res.getNode();
27860b57cec5SDimitry Andric   }
27870b57cec5SDimitry Andric 
Select(SDNode * N,bool LateMask,unsigned * InstCnt=nullptr)27880b57cec5SDimitry Andric   SDNode *Select(SDNode *N, bool LateMask, unsigned *InstCnt = nullptr) {
27890b57cec5SDimitry Andric     // Fill in BitGroups.
27900b57cec5SDimitry Andric     collectBitGroups(LateMask);
27910b57cec5SDimitry Andric     if (BitGroups.empty())
27920b57cec5SDimitry Andric       return nullptr;
27930b57cec5SDimitry Andric 
27940b57cec5SDimitry Andric     // For 64-bit values, figure out when we can use 32-bit instructions.
27950b57cec5SDimitry Andric     if (Bits.size() == 64)
27960b57cec5SDimitry Andric       assignRepl32BitGroups();
27970b57cec5SDimitry Andric 
27980b57cec5SDimitry Andric     // Fill in ValueRotsVec.
27990b57cec5SDimitry Andric     collectValueRotInfo();
28000b57cec5SDimitry Andric 
28010b57cec5SDimitry Andric     if (Bits.size() == 32) {
28020b57cec5SDimitry Andric       return Select32(N, LateMask, InstCnt);
28030b57cec5SDimitry Andric     } else {
28040b57cec5SDimitry Andric       assert(Bits.size() == 64 && "Not 64 bits here?");
28050b57cec5SDimitry Andric       return Select64(N, LateMask, InstCnt);
28060b57cec5SDimitry Andric     }
28070b57cec5SDimitry Andric 
28080b57cec5SDimitry Andric     return nullptr;
28090b57cec5SDimitry Andric   }
28100b57cec5SDimitry Andric 
eraseMatchingBitGroups(function_ref<bool (const BitGroup &)> F)28110b57cec5SDimitry Andric   void eraseMatchingBitGroups(function_ref<bool(const BitGroup &)> F) {
2812e8d8bef9SDimitry Andric     erase_if(BitGroups, F);
28130b57cec5SDimitry Andric   }
28140b57cec5SDimitry Andric 
28150b57cec5SDimitry Andric   SmallVector<ValueBit, 64> Bits;
28160b57cec5SDimitry Andric 
2817480093f4SDimitry Andric   bool NeedMask = false;
28180b57cec5SDimitry Andric   SmallVector<unsigned, 64> RLAmt;
28190b57cec5SDimitry Andric 
28200b57cec5SDimitry Andric   SmallVector<BitGroup, 16> BitGroups;
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric   DenseMap<std::pair<SDValue, unsigned>, ValueRotInfo> ValueRots;
28230b57cec5SDimitry Andric   SmallVector<ValueRotInfo, 16> ValueRotsVec;
28240b57cec5SDimitry Andric 
2825480093f4SDimitry Andric   SelectionDAG *CurDAG = nullptr;
28260b57cec5SDimitry Andric 
28270b57cec5SDimitry Andric public:
BitPermutationSelector(SelectionDAG * DAG)28280b57cec5SDimitry Andric   BitPermutationSelector(SelectionDAG *DAG)
28290b57cec5SDimitry Andric     : CurDAG(DAG) {}
28300b57cec5SDimitry Andric 
28310b57cec5SDimitry Andric   // Here we try to match complex bit permutations into a set of
28320b57cec5SDimitry Andric   // rotate-and-shift/shift/and/or instructions, using a set of heuristics
28330b57cec5SDimitry Andric   // known to produce optimal code for common cases (like i32 byte swapping).
Select(SDNode * N)28340b57cec5SDimitry Andric   SDNode *Select(SDNode *N) {
28350b57cec5SDimitry Andric     Memoizer.clear();
28360b57cec5SDimitry Andric     auto Result =
28370b57cec5SDimitry Andric         getValueBits(SDValue(N, 0), N->getValueType(0).getSizeInBits());
28380b57cec5SDimitry Andric     if (!Result.first)
28390b57cec5SDimitry Andric       return nullptr;
28400b57cec5SDimitry Andric     Bits = std::move(*Result.second);
28410b57cec5SDimitry Andric 
28420b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Considering bit-permutation-based instruction"
28430b57cec5SDimitry Andric                          " selection for:    ");
28440b57cec5SDimitry Andric     LLVM_DEBUG(N->dump(CurDAG));
28450b57cec5SDimitry Andric 
28460b57cec5SDimitry Andric     // Fill it RLAmt and set NeedMask.
28470b57cec5SDimitry Andric     computeRotationAmounts();
28480b57cec5SDimitry Andric 
28490b57cec5SDimitry Andric     if (!NeedMask)
28500b57cec5SDimitry Andric       return Select(N, false);
28510b57cec5SDimitry Andric 
28520b57cec5SDimitry Andric     // We currently have two techniques for handling results with zeros: early
28530b57cec5SDimitry Andric     // masking (the default) and late masking. Late masking is sometimes more
28540b57cec5SDimitry Andric     // efficient, but because the structure of the bit groups is different, it
28550b57cec5SDimitry Andric     // is hard to tell without generating both and comparing the results. With
28560b57cec5SDimitry Andric     // late masking, we ignore zeros in the resulting value when inserting each
28570b57cec5SDimitry Andric     // set of bit groups, and then mask in the zeros at the end. With early
28580b57cec5SDimitry Andric     // masking, we only insert the non-zero parts of the result at every step.
28590b57cec5SDimitry Andric 
28600b57cec5SDimitry Andric     unsigned InstCnt = 0, InstCntLateMask = 0;
28610b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\tEarly masking:\n");
28620b57cec5SDimitry Andric     SDNode *RN = Select(N, false, &InstCnt);
28630b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\t\tisel would use " << InstCnt << " instructions\n");
28640b57cec5SDimitry Andric 
28650b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\tLate masking:\n");
28660b57cec5SDimitry Andric     SDNode *RNLM = Select(N, true, &InstCntLateMask);
28670b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\t\tisel would use " << InstCntLateMask
28680b57cec5SDimitry Andric                       << " instructions\n");
28690b57cec5SDimitry Andric 
28700b57cec5SDimitry Andric     if (InstCnt <= InstCntLateMask) {
28710b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\tUsing early-masking for isel\n");
28720b57cec5SDimitry Andric       return RN;
28730b57cec5SDimitry Andric     }
28740b57cec5SDimitry Andric 
28750b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\tUsing late-masking for isel\n");
28760b57cec5SDimitry Andric     return RNLM;
28770b57cec5SDimitry Andric   }
28780b57cec5SDimitry Andric };
28790b57cec5SDimitry Andric 
28800b57cec5SDimitry Andric class IntegerCompareEliminator {
28810b57cec5SDimitry Andric   SelectionDAG *CurDAG;
28820b57cec5SDimitry Andric   PPCDAGToDAGISel *S;
28830b57cec5SDimitry Andric   // Conversion type for interpreting results of a 32-bit instruction as
28840b57cec5SDimitry Andric   // a 64-bit value or vice versa.
28850b57cec5SDimitry Andric   enum ExtOrTruncConversion { Ext, Trunc };
28860b57cec5SDimitry Andric 
28870b57cec5SDimitry Andric   // Modifiers to guide how an ISD::SETCC node's result is to be computed
28880b57cec5SDimitry Andric   // in a GPR.
28890b57cec5SDimitry Andric   // ZExtOrig - use the original condition code, zero-extend value
28900b57cec5SDimitry Andric   // ZExtInvert - invert the condition code, zero-extend value
28910b57cec5SDimitry Andric   // SExtOrig - use the original condition code, sign-extend value
28920b57cec5SDimitry Andric   // SExtInvert - invert the condition code, sign-extend value
28930b57cec5SDimitry Andric   enum SetccInGPROpts { ZExtOrig, ZExtInvert, SExtOrig, SExtInvert };
28940b57cec5SDimitry Andric 
28950b57cec5SDimitry Andric   // Comparisons against zero to emit GPR code sequences for. Each of these
28960b57cec5SDimitry Andric   // sequences may need to be emitted for two or more equivalent patterns.
28970b57cec5SDimitry Andric   // For example (a >= 0) == (a > -1). The direction of the comparison (</>)
28980b57cec5SDimitry Andric   // matters as well as the extension type: sext (-1/0), zext (1/0).
28990b57cec5SDimitry Andric   // GEZExt - (zext (LHS >= 0))
29000b57cec5SDimitry Andric   // GESExt - (sext (LHS >= 0))
29010b57cec5SDimitry Andric   // LEZExt - (zext (LHS <= 0))
29020b57cec5SDimitry Andric   // LESExt - (sext (LHS <= 0))
29030b57cec5SDimitry Andric   enum ZeroCompare { GEZExt, GESExt, LEZExt, LESExt };
29040b57cec5SDimitry Andric 
29050b57cec5SDimitry Andric   SDNode *tryEXTEND(SDNode *N);
29060b57cec5SDimitry Andric   SDNode *tryLogicOpOfCompares(SDNode *N);
29070b57cec5SDimitry Andric   SDValue computeLogicOpInGPR(SDValue LogicOp);
29080b57cec5SDimitry Andric   SDValue signExtendInputIfNeeded(SDValue Input);
29090b57cec5SDimitry Andric   SDValue zeroExtendInputIfNeeded(SDValue Input);
29100b57cec5SDimitry Andric   SDValue addExtOrTrunc(SDValue NatWidthRes, ExtOrTruncConversion Conv);
29110b57cec5SDimitry Andric   SDValue getCompoundZeroComparisonInGPR(SDValue LHS, SDLoc dl,
29120b57cec5SDimitry Andric                                         ZeroCompare CmpTy);
29130b57cec5SDimitry Andric   SDValue get32BitZExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
29140b57cec5SDimitry Andric                               int64_t RHSValue, SDLoc dl);
29150b57cec5SDimitry Andric  SDValue get32BitSExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
29160b57cec5SDimitry Andric                               int64_t RHSValue, SDLoc dl);
29170b57cec5SDimitry Andric   SDValue get64BitZExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
29180b57cec5SDimitry Andric                               int64_t RHSValue, SDLoc dl);
29190b57cec5SDimitry Andric   SDValue get64BitSExtCompare(SDValue LHS, SDValue RHS, ISD::CondCode CC,
29200b57cec5SDimitry Andric                               int64_t RHSValue, SDLoc dl);
29210b57cec5SDimitry Andric   SDValue getSETCCInGPR(SDValue Compare, SetccInGPROpts ConvOpts);
29220b57cec5SDimitry Andric 
29230b57cec5SDimitry Andric public:
IntegerCompareEliminator(SelectionDAG * DAG,PPCDAGToDAGISel * Sel)29240b57cec5SDimitry Andric   IntegerCompareEliminator(SelectionDAG *DAG,
29250b57cec5SDimitry Andric                            PPCDAGToDAGISel *Sel) : CurDAG(DAG), S(Sel) {
29260b57cec5SDimitry Andric     assert(CurDAG->getTargetLoweringInfo()
29270b57cec5SDimitry Andric            .getPointerTy(CurDAG->getDataLayout()).getSizeInBits() == 64 &&
29280b57cec5SDimitry Andric            "Only expecting to use this on 64 bit targets.");
29290b57cec5SDimitry Andric   }
Select(SDNode * N)29300b57cec5SDimitry Andric   SDNode *Select(SDNode *N) {
29310b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_None)
29320b57cec5SDimitry Andric       return nullptr;
29330b57cec5SDimitry Andric     switch (N->getOpcode()) {
29340b57cec5SDimitry Andric     default: break;
29350b57cec5SDimitry Andric     case ISD::ZERO_EXTEND:
29360b57cec5SDimitry Andric       if (CmpInGPR == ICGPR_Sext || CmpInGPR == ICGPR_SextI32 ||
29370b57cec5SDimitry Andric           CmpInGPR == ICGPR_SextI64)
29380b57cec5SDimitry Andric         return nullptr;
2939bdd1243dSDimitry Andric       [[fallthrough]];
29400b57cec5SDimitry Andric     case ISD::SIGN_EXTEND:
29410b57cec5SDimitry Andric       if (CmpInGPR == ICGPR_Zext || CmpInGPR == ICGPR_ZextI32 ||
29420b57cec5SDimitry Andric           CmpInGPR == ICGPR_ZextI64)
29430b57cec5SDimitry Andric         return nullptr;
29440b57cec5SDimitry Andric       return tryEXTEND(N);
29450b57cec5SDimitry Andric     case ISD::AND:
29460b57cec5SDimitry Andric     case ISD::OR:
29470b57cec5SDimitry Andric     case ISD::XOR:
29480b57cec5SDimitry Andric       return tryLogicOpOfCompares(N);
29490b57cec5SDimitry Andric     }
29500b57cec5SDimitry Andric     return nullptr;
29510b57cec5SDimitry Andric   }
29520b57cec5SDimitry Andric };
29530b57cec5SDimitry Andric 
29540b57cec5SDimitry Andric // The obvious case for wanting to keep the value in a GPR. Namely, the
29550b57cec5SDimitry Andric // result of the comparison is actually needed in a GPR.
tryEXTEND(SDNode * N)29560b57cec5SDimitry Andric SDNode *IntegerCompareEliminator::tryEXTEND(SDNode *N) {
29570b57cec5SDimitry Andric   assert((N->getOpcode() == ISD::ZERO_EXTEND ||
29580b57cec5SDimitry Andric           N->getOpcode() == ISD::SIGN_EXTEND) &&
29590b57cec5SDimitry Andric          "Expecting a zero/sign extend node!");
29600b57cec5SDimitry Andric   SDValue WideRes;
29610b57cec5SDimitry Andric   // If we are zero-extending the result of a logical operation on i1
29620b57cec5SDimitry Andric   // values, we can keep the values in GPRs.
296306c3fb27SDimitry Andric   if (ISD::isBitwiseLogicOp(N->getOperand(0).getOpcode()) &&
29640b57cec5SDimitry Andric       N->getOperand(0).getValueType() == MVT::i1 &&
29650b57cec5SDimitry Andric       N->getOpcode() == ISD::ZERO_EXTEND)
29660b57cec5SDimitry Andric     WideRes = computeLogicOpInGPR(N->getOperand(0));
29670b57cec5SDimitry Andric   else if (N->getOperand(0).getOpcode() != ISD::SETCC)
29680b57cec5SDimitry Andric     return nullptr;
29690b57cec5SDimitry Andric   else
29700b57cec5SDimitry Andric     WideRes =
29710b57cec5SDimitry Andric       getSETCCInGPR(N->getOperand(0),
29720b57cec5SDimitry Andric                     N->getOpcode() == ISD::SIGN_EXTEND ?
29730b57cec5SDimitry Andric                     SetccInGPROpts::SExtOrig : SetccInGPROpts::ZExtOrig);
29740b57cec5SDimitry Andric 
29750b57cec5SDimitry Andric   if (!WideRes)
29760b57cec5SDimitry Andric     return nullptr;
29770b57cec5SDimitry Andric 
29780b57cec5SDimitry Andric   SDLoc dl(N);
29790b57cec5SDimitry Andric   bool Input32Bit = WideRes.getValueType() == MVT::i32;
29800b57cec5SDimitry Andric   bool Output32Bit = N->getValueType(0) == MVT::i32;
29810b57cec5SDimitry Andric 
29820b57cec5SDimitry Andric   NumSextSetcc += N->getOpcode() == ISD::SIGN_EXTEND ? 1 : 0;
29830b57cec5SDimitry Andric   NumZextSetcc += N->getOpcode() == ISD::SIGN_EXTEND ? 0 : 1;
29840b57cec5SDimitry Andric 
29850b57cec5SDimitry Andric   SDValue ConvOp = WideRes;
29860b57cec5SDimitry Andric   if (Input32Bit != Output32Bit)
29870b57cec5SDimitry Andric     ConvOp = addExtOrTrunc(WideRes, Input32Bit ? ExtOrTruncConversion::Ext :
29880b57cec5SDimitry Andric                            ExtOrTruncConversion::Trunc);
29890b57cec5SDimitry Andric   return ConvOp.getNode();
29900b57cec5SDimitry Andric }
29910b57cec5SDimitry Andric 
29920b57cec5SDimitry Andric // Attempt to perform logical operations on the results of comparisons while
29930b57cec5SDimitry Andric // keeping the values in GPRs. Without doing so, these would end up being
29940b57cec5SDimitry Andric // lowered to CR-logical operations which suffer from significant latency and
29950b57cec5SDimitry Andric // low ILP.
tryLogicOpOfCompares(SDNode * N)29960b57cec5SDimitry Andric SDNode *IntegerCompareEliminator::tryLogicOpOfCompares(SDNode *N) {
29970b57cec5SDimitry Andric   if (N->getValueType(0) != MVT::i1)
29980b57cec5SDimitry Andric     return nullptr;
299906c3fb27SDimitry Andric   assert(ISD::isBitwiseLogicOp(N->getOpcode()) &&
30000b57cec5SDimitry Andric          "Expected a logic operation on setcc results.");
30010b57cec5SDimitry Andric   SDValue LoweredLogical = computeLogicOpInGPR(SDValue(N, 0));
30020b57cec5SDimitry Andric   if (!LoweredLogical)
30030b57cec5SDimitry Andric     return nullptr;
30040b57cec5SDimitry Andric 
30050b57cec5SDimitry Andric   SDLoc dl(N);
30060b57cec5SDimitry Andric   bool IsBitwiseNegate = LoweredLogical.getMachineOpcode() == PPC::XORI8;
30070b57cec5SDimitry Andric   unsigned SubRegToExtract = IsBitwiseNegate ? PPC::sub_eq : PPC::sub_gt;
30080b57cec5SDimitry Andric   SDValue CR0Reg = CurDAG->getRegister(PPC::CR0, MVT::i32);
30090b57cec5SDimitry Andric   SDValue LHS = LoweredLogical.getOperand(0);
30100b57cec5SDimitry Andric   SDValue RHS = LoweredLogical.getOperand(1);
30110b57cec5SDimitry Andric   SDValue WideOp;
30120b57cec5SDimitry Andric   SDValue OpToConvToRecForm;
30130b57cec5SDimitry Andric 
30140b57cec5SDimitry Andric   // Look through any 32-bit to 64-bit implicit extend nodes to find the
30150b57cec5SDimitry Andric   // opcode that is input to the XORI.
30160b57cec5SDimitry Andric   if (IsBitwiseNegate &&
30170b57cec5SDimitry Andric       LoweredLogical.getOperand(0).getMachineOpcode() == PPC::INSERT_SUBREG)
30180b57cec5SDimitry Andric     OpToConvToRecForm = LoweredLogical.getOperand(0).getOperand(1);
30190b57cec5SDimitry Andric   else if (IsBitwiseNegate)
30200b57cec5SDimitry Andric     // If the input to the XORI isn't an extension, that's what we're after.
30210b57cec5SDimitry Andric     OpToConvToRecForm = LoweredLogical.getOperand(0);
30220b57cec5SDimitry Andric   else
30230b57cec5SDimitry Andric     // If this is not an XORI, it is a reg-reg logical op and we can convert
30240b57cec5SDimitry Andric     // it to record-form.
30250b57cec5SDimitry Andric     OpToConvToRecForm = LoweredLogical;
30260b57cec5SDimitry Andric 
30270b57cec5SDimitry Andric   // Get the record-form version of the node we're looking to use to get the
30280b57cec5SDimitry Andric   // CR result from.
30290b57cec5SDimitry Andric   uint16_t NonRecOpc = OpToConvToRecForm.getMachineOpcode();
30300b57cec5SDimitry Andric   int NewOpc = PPCInstrInfo::getRecordFormOpcode(NonRecOpc);
30310b57cec5SDimitry Andric 
30320b57cec5SDimitry Andric   // Convert the right node to record-form. This is either the logical we're
30330b57cec5SDimitry Andric   // looking at or it is the input node to the negation (if we're looking at
30340b57cec5SDimitry Andric   // a bitwise negation).
30350b57cec5SDimitry Andric   if (NewOpc != -1 && IsBitwiseNegate) {
30360b57cec5SDimitry Andric     // The input to the XORI has a record-form. Use it.
30370b57cec5SDimitry Andric     assert(LoweredLogical.getConstantOperandVal(1) == 1 &&
30380b57cec5SDimitry Andric            "Expected a PPC::XORI8 only for bitwise negation.");
30390b57cec5SDimitry Andric     // Emit the record-form instruction.
30400b57cec5SDimitry Andric     std::vector<SDValue> Ops;
30410b57cec5SDimitry Andric     for (int i = 0, e = OpToConvToRecForm.getNumOperands(); i < e; i++)
30420b57cec5SDimitry Andric       Ops.push_back(OpToConvToRecForm.getOperand(i));
30430b57cec5SDimitry Andric 
30440b57cec5SDimitry Andric     WideOp =
30450b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(NewOpc, dl,
30460b57cec5SDimitry Andric                                      OpToConvToRecForm.getValueType(),
30470b57cec5SDimitry Andric                                      MVT::Glue, Ops), 0);
30480b57cec5SDimitry Andric   } else {
30490b57cec5SDimitry Andric     assert((NewOpc != -1 || !IsBitwiseNegate) &&
30500b57cec5SDimitry Andric            "No record form available for AND8/OR8/XOR8?");
30510b57cec5SDimitry Andric     WideOp =
3052480093f4SDimitry Andric         SDValue(CurDAG->getMachineNode(NewOpc == -1 ? PPC::ANDI8_rec : NewOpc,
3053480093f4SDimitry Andric                                        dl, MVT::i64, MVT::Glue, LHS, RHS),
3054480093f4SDimitry Andric                 0);
30550b57cec5SDimitry Andric   }
30560b57cec5SDimitry Andric 
30570b57cec5SDimitry Andric   // Select this node to a single bit from CR0 set by the record-form node
30580b57cec5SDimitry Andric   // just created. For bitwise negation, use the EQ bit which is the equivalent
30590b57cec5SDimitry Andric   // of negating the result (i.e. it is a bit set when the result of the
30600b57cec5SDimitry Andric   // operation is zero).
30610b57cec5SDimitry Andric   SDValue SRIdxVal =
30620b57cec5SDimitry Andric     CurDAG->getTargetConstant(SubRegToExtract, dl, MVT::i32);
30630b57cec5SDimitry Andric   SDValue CRBit =
30640b57cec5SDimitry Andric     SDValue(CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl,
30650b57cec5SDimitry Andric                                    MVT::i1, CR0Reg, SRIdxVal,
30660b57cec5SDimitry Andric                                    WideOp.getValue(1)), 0);
30670b57cec5SDimitry Andric   return CRBit.getNode();
30680b57cec5SDimitry Andric }
30690b57cec5SDimitry Andric 
30700b57cec5SDimitry Andric // Lower a logical operation on i1 values into a GPR sequence if possible.
30710b57cec5SDimitry Andric // The result can be kept in a GPR if requested.
30720b57cec5SDimitry Andric // Three types of inputs can be handled:
30730b57cec5SDimitry Andric // - SETCC
30740b57cec5SDimitry Andric // - TRUNCATE
30750b57cec5SDimitry Andric // - Logical operation (AND/OR/XOR)
30760b57cec5SDimitry Andric // There is also a special case that is handled (namely a complement operation
30770b57cec5SDimitry Andric // achieved with xor %a, -1).
computeLogicOpInGPR(SDValue LogicOp)30780b57cec5SDimitry Andric SDValue IntegerCompareEliminator::computeLogicOpInGPR(SDValue LogicOp) {
307906c3fb27SDimitry Andric   assert(ISD::isBitwiseLogicOp(LogicOp.getOpcode()) &&
30800b57cec5SDimitry Andric         "Can only handle logic operations here.");
30810b57cec5SDimitry Andric   assert(LogicOp.getValueType() == MVT::i1 &&
30820b57cec5SDimitry Andric          "Can only handle logic operations on i1 values here.");
30830b57cec5SDimitry Andric   SDLoc dl(LogicOp);
30840b57cec5SDimitry Andric   SDValue LHS, RHS;
30850b57cec5SDimitry Andric 
30860b57cec5SDimitry Andric  // Special case: xor %a, -1
30870b57cec5SDimitry Andric   bool IsBitwiseNegation = isBitwiseNot(LogicOp);
30880b57cec5SDimitry Andric 
30890b57cec5SDimitry Andric   // Produces a GPR sequence for each operand of the binary logic operation.
30900b57cec5SDimitry Andric   // For SETCC, it produces the respective comparison, for TRUNCATE it truncates
30910b57cec5SDimitry Andric   // the value in a GPR and for logic operations, it will recursively produce
30920b57cec5SDimitry Andric   // a GPR sequence for the operation.
30930b57cec5SDimitry Andric  auto getLogicOperand = [&] (SDValue Operand) -> SDValue {
30940b57cec5SDimitry Andric     unsigned OperandOpcode = Operand.getOpcode();
30950b57cec5SDimitry Andric     if (OperandOpcode == ISD::SETCC)
30960b57cec5SDimitry Andric       return getSETCCInGPR(Operand, SetccInGPROpts::ZExtOrig);
30970b57cec5SDimitry Andric     else if (OperandOpcode == ISD::TRUNCATE) {
30980b57cec5SDimitry Andric       SDValue InputOp = Operand.getOperand(0);
30990b57cec5SDimitry Andric      EVT InVT = InputOp.getValueType();
31000b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(InVT == MVT::i32 ? PPC::RLDICL_32 :
31010b57cec5SDimitry Andric                                             PPC::RLDICL, dl, InVT, InputOp,
31020b57cec5SDimitry Andric                                             S->getI64Imm(0, dl),
31030b57cec5SDimitry Andric                                             S->getI64Imm(63, dl)), 0);
310406c3fb27SDimitry Andric     } else if (ISD::isBitwiseLogicOp(OperandOpcode))
31050b57cec5SDimitry Andric       return computeLogicOpInGPR(Operand);
31060b57cec5SDimitry Andric     return SDValue();
31070b57cec5SDimitry Andric   };
31080b57cec5SDimitry Andric   LHS = getLogicOperand(LogicOp.getOperand(0));
31090b57cec5SDimitry Andric   RHS = getLogicOperand(LogicOp.getOperand(1));
31100b57cec5SDimitry Andric 
31110b57cec5SDimitry Andric   // If a GPR sequence can't be produced for the LHS we can't proceed.
31120b57cec5SDimitry Andric   // Not producing a GPR sequence for the RHS is only a problem if this isn't
31130b57cec5SDimitry Andric   // a bitwise negation operation.
31140b57cec5SDimitry Andric   if (!LHS || (!RHS && !IsBitwiseNegation))
31150b57cec5SDimitry Andric     return SDValue();
31160b57cec5SDimitry Andric 
31170b57cec5SDimitry Andric   NumLogicOpsOnComparison++;
31180b57cec5SDimitry Andric 
31190b57cec5SDimitry Andric   // We will use the inputs as 64-bit values.
31200b57cec5SDimitry Andric   if (LHS.getValueType() == MVT::i32)
31210b57cec5SDimitry Andric     LHS = addExtOrTrunc(LHS, ExtOrTruncConversion::Ext);
31220b57cec5SDimitry Andric   if (!IsBitwiseNegation && RHS.getValueType() == MVT::i32)
31230b57cec5SDimitry Andric     RHS = addExtOrTrunc(RHS, ExtOrTruncConversion::Ext);
31240b57cec5SDimitry Andric 
31250b57cec5SDimitry Andric   unsigned NewOpc;
31260b57cec5SDimitry Andric   switch (LogicOp.getOpcode()) {
31270b57cec5SDimitry Andric   default: llvm_unreachable("Unknown logic operation.");
31280b57cec5SDimitry Andric   case ISD::AND: NewOpc = PPC::AND8; break;
31290b57cec5SDimitry Andric   case ISD::OR:  NewOpc = PPC::OR8;  break;
31300b57cec5SDimitry Andric   case ISD::XOR: NewOpc = PPC::XOR8; break;
31310b57cec5SDimitry Andric   }
31320b57cec5SDimitry Andric 
31330b57cec5SDimitry Andric   if (IsBitwiseNegation) {
31340b57cec5SDimitry Andric     RHS = S->getI64Imm(1, dl);
31350b57cec5SDimitry Andric     NewOpc = PPC::XORI8;
31360b57cec5SDimitry Andric   }
31370b57cec5SDimitry Andric 
31380b57cec5SDimitry Andric   return SDValue(CurDAG->getMachineNode(NewOpc, dl, MVT::i64, LHS, RHS), 0);
31390b57cec5SDimitry Andric 
31400b57cec5SDimitry Andric }
31410b57cec5SDimitry Andric 
31420b57cec5SDimitry Andric /// If the value isn't guaranteed to be sign-extended to 64-bits, extend it.
31430b57cec5SDimitry Andric /// Otherwise just reinterpret it as a 64-bit value.
31440b57cec5SDimitry Andric /// Useful when emitting comparison code for 32-bit values without using
31450b57cec5SDimitry Andric /// the compare instruction (which only considers the lower 32-bits).
signExtendInputIfNeeded(SDValue Input)31460b57cec5SDimitry Andric SDValue IntegerCompareEliminator::signExtendInputIfNeeded(SDValue Input) {
31470b57cec5SDimitry Andric   assert(Input.getValueType() == MVT::i32 &&
31480b57cec5SDimitry Andric          "Can only sign-extend 32-bit values here.");
31490b57cec5SDimitry Andric   unsigned Opc = Input.getOpcode();
31500b57cec5SDimitry Andric 
31510b57cec5SDimitry Andric   // The value was sign extended and then truncated to 32-bits. No need to
31520b57cec5SDimitry Andric   // sign extend it again.
31530b57cec5SDimitry Andric   if (Opc == ISD::TRUNCATE &&
31540b57cec5SDimitry Andric       (Input.getOperand(0).getOpcode() == ISD::AssertSext ||
31550b57cec5SDimitry Andric        Input.getOperand(0).getOpcode() == ISD::SIGN_EXTEND))
31560b57cec5SDimitry Andric     return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
31570b57cec5SDimitry Andric 
31580b57cec5SDimitry Andric   LoadSDNode *InputLoad = dyn_cast<LoadSDNode>(Input);
31590b57cec5SDimitry Andric   // The input is a sign-extending load. All ppc sign-extending loads
31600b57cec5SDimitry Andric   // sign-extend to the full 64-bits.
31610b57cec5SDimitry Andric   if (InputLoad && InputLoad->getExtensionType() == ISD::SEXTLOAD)
31620b57cec5SDimitry Andric     return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
31630b57cec5SDimitry Andric 
31640b57cec5SDimitry Andric   ConstantSDNode *InputConst = dyn_cast<ConstantSDNode>(Input);
31650b57cec5SDimitry Andric   // We don't sign-extend constants.
31660b57cec5SDimitry Andric   if (InputConst)
31670b57cec5SDimitry Andric     return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
31680b57cec5SDimitry Andric 
31690b57cec5SDimitry Andric   SDLoc dl(Input);
31700b57cec5SDimitry Andric   SignExtensionsAdded++;
31710b57cec5SDimitry Andric   return SDValue(CurDAG->getMachineNode(PPC::EXTSW_32_64, dl,
31720b57cec5SDimitry Andric                                         MVT::i64, Input), 0);
31730b57cec5SDimitry Andric }
31740b57cec5SDimitry Andric 
31750b57cec5SDimitry Andric /// If the value isn't guaranteed to be zero-extended to 64-bits, extend it.
31760b57cec5SDimitry Andric /// Otherwise just reinterpret it as a 64-bit value.
31770b57cec5SDimitry Andric /// Useful when emitting comparison code for 32-bit values without using
31780b57cec5SDimitry Andric /// the compare instruction (which only considers the lower 32-bits).
zeroExtendInputIfNeeded(SDValue Input)31790b57cec5SDimitry Andric SDValue IntegerCompareEliminator::zeroExtendInputIfNeeded(SDValue Input) {
31800b57cec5SDimitry Andric   assert(Input.getValueType() == MVT::i32 &&
31810b57cec5SDimitry Andric          "Can only zero-extend 32-bit values here.");
31820b57cec5SDimitry Andric   unsigned Opc = Input.getOpcode();
31830b57cec5SDimitry Andric 
31840b57cec5SDimitry Andric   // The only condition under which we can omit the actual extend instruction:
31850b57cec5SDimitry Andric   // - The value is a positive constant
31860b57cec5SDimitry Andric   // - The value comes from a load that isn't a sign-extending load
31870b57cec5SDimitry Andric   // An ISD::TRUNCATE needs to be zero-extended unless it is fed by a zext.
31880b57cec5SDimitry Andric   bool IsTruncateOfZExt = Opc == ISD::TRUNCATE &&
31890b57cec5SDimitry Andric     (Input.getOperand(0).getOpcode() == ISD::AssertZext ||
31900b57cec5SDimitry Andric      Input.getOperand(0).getOpcode() == ISD::ZERO_EXTEND);
31910b57cec5SDimitry Andric   if (IsTruncateOfZExt)
31920b57cec5SDimitry Andric     return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
31930b57cec5SDimitry Andric 
31940b57cec5SDimitry Andric   ConstantSDNode *InputConst = dyn_cast<ConstantSDNode>(Input);
31950b57cec5SDimitry Andric   if (InputConst && InputConst->getSExtValue() >= 0)
31960b57cec5SDimitry Andric     return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
31970b57cec5SDimitry Andric 
31980b57cec5SDimitry Andric   LoadSDNode *InputLoad = dyn_cast<LoadSDNode>(Input);
31990b57cec5SDimitry Andric   // The input is a load that doesn't sign-extend (it will be zero-extended).
32000b57cec5SDimitry Andric   if (InputLoad && InputLoad->getExtensionType() != ISD::SEXTLOAD)
32010b57cec5SDimitry Andric     return addExtOrTrunc(Input, ExtOrTruncConversion::Ext);
32020b57cec5SDimitry Andric 
32030b57cec5SDimitry Andric   // None of the above, need to zero-extend.
32040b57cec5SDimitry Andric   SDLoc dl(Input);
32050b57cec5SDimitry Andric   ZeroExtensionsAdded++;
32060b57cec5SDimitry Andric   return SDValue(CurDAG->getMachineNode(PPC::RLDICL_32_64, dl, MVT::i64, Input,
32070b57cec5SDimitry Andric                                         S->getI64Imm(0, dl),
32080b57cec5SDimitry Andric                                         S->getI64Imm(32, dl)), 0);
32090b57cec5SDimitry Andric }
32100b57cec5SDimitry Andric 
32110b57cec5SDimitry Andric // Handle a 32-bit value in a 64-bit register and vice-versa. These are of
32120b57cec5SDimitry Andric // course not actual zero/sign extensions that will generate machine code,
32130b57cec5SDimitry Andric // they're just a way to reinterpret a 32 bit value in a register as a
32140b57cec5SDimitry Andric // 64 bit value and vice-versa.
addExtOrTrunc(SDValue NatWidthRes,ExtOrTruncConversion Conv)32150b57cec5SDimitry Andric SDValue IntegerCompareEliminator::addExtOrTrunc(SDValue NatWidthRes,
32160b57cec5SDimitry Andric                                                 ExtOrTruncConversion Conv) {
32170b57cec5SDimitry Andric   SDLoc dl(NatWidthRes);
32180b57cec5SDimitry Andric 
32190b57cec5SDimitry Andric   // For reinterpreting 32-bit values as 64 bit values, we generate
32200b57cec5SDimitry Andric   // INSERT_SUBREG IMPLICIT_DEF:i64, <input>, TargetConstant:i32<1>
32210b57cec5SDimitry Andric   if (Conv == ExtOrTruncConversion::Ext) {
32220b57cec5SDimitry Andric     SDValue ImDef(CurDAG->getMachineNode(PPC::IMPLICIT_DEF, dl, MVT::i64), 0);
32230b57cec5SDimitry Andric     SDValue SubRegIdx =
32240b57cec5SDimitry Andric       CurDAG->getTargetConstant(PPC::sub_32, dl, MVT::i32);
32250b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::INSERT_SUBREG, dl, MVT::i64,
32260b57cec5SDimitry Andric                                           ImDef, NatWidthRes, SubRegIdx), 0);
32270b57cec5SDimitry Andric   }
32280b57cec5SDimitry Andric 
32290b57cec5SDimitry Andric   assert(Conv == ExtOrTruncConversion::Trunc &&
32300b57cec5SDimitry Andric          "Unknown convertion between 32 and 64 bit values.");
32310b57cec5SDimitry Andric   // For reinterpreting 64-bit values as 32-bit values, we just need to
32320b57cec5SDimitry Andric   // EXTRACT_SUBREG (i.e. extract the low word).
32330b57cec5SDimitry Andric   SDValue SubRegIdx =
32340b57cec5SDimitry Andric     CurDAG->getTargetConstant(PPC::sub_32, dl, MVT::i32);
32350b57cec5SDimitry Andric   return SDValue(CurDAG->getMachineNode(PPC::EXTRACT_SUBREG, dl, MVT::i32,
32360b57cec5SDimitry Andric                                         NatWidthRes, SubRegIdx), 0);
32370b57cec5SDimitry Andric }
32380b57cec5SDimitry Andric 
32390b57cec5SDimitry Andric // Produce a GPR sequence for compound comparisons (<=, >=) against zero.
32400b57cec5SDimitry Andric // Handle both zero-extensions and sign-extensions.
32410b57cec5SDimitry Andric SDValue
getCompoundZeroComparisonInGPR(SDValue LHS,SDLoc dl,ZeroCompare CmpTy)32420b57cec5SDimitry Andric IntegerCompareEliminator::getCompoundZeroComparisonInGPR(SDValue LHS, SDLoc dl,
32430b57cec5SDimitry Andric                                                          ZeroCompare CmpTy) {
32440b57cec5SDimitry Andric   EVT InVT = LHS.getValueType();
32450b57cec5SDimitry Andric   bool Is32Bit = InVT == MVT::i32;
32460b57cec5SDimitry Andric   SDValue ToExtend;
32470b57cec5SDimitry Andric 
32480b57cec5SDimitry Andric   // Produce the value that needs to be either zero or sign extended.
32490b57cec5SDimitry Andric   switch (CmpTy) {
32500b57cec5SDimitry Andric   case ZeroCompare::GEZExt:
32510b57cec5SDimitry Andric   case ZeroCompare::GESExt:
32520b57cec5SDimitry Andric     ToExtend = SDValue(CurDAG->getMachineNode(Is32Bit ? PPC::NOR : PPC::NOR8,
32530b57cec5SDimitry Andric                                               dl, InVT, LHS, LHS), 0);
32540b57cec5SDimitry Andric     break;
32550b57cec5SDimitry Andric   case ZeroCompare::LEZExt:
32560b57cec5SDimitry Andric   case ZeroCompare::LESExt: {
32570b57cec5SDimitry Andric     if (Is32Bit) {
32580b57cec5SDimitry Andric       // Upper 32 bits cannot be undefined for this sequence.
32590b57cec5SDimitry Andric       LHS = signExtendInputIfNeeded(LHS);
32600b57cec5SDimitry Andric       SDValue Neg =
32610b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::NEG8, dl, MVT::i64, LHS), 0);
32620b57cec5SDimitry Andric       ToExtend =
32630b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
32640b57cec5SDimitry Andric                                        Neg, S->getI64Imm(1, dl),
32650b57cec5SDimitry Andric                                        S->getI64Imm(63, dl)), 0);
32660b57cec5SDimitry Andric     } else {
32670b57cec5SDimitry Andric       SDValue Addi =
32680b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, LHS,
32690b57cec5SDimitry Andric                                        S->getI64Imm(~0ULL, dl)), 0);
32700b57cec5SDimitry Andric       ToExtend = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
32710b57cec5SDimitry Andric                                                 Addi, LHS), 0);
32720b57cec5SDimitry Andric     }
32730b57cec5SDimitry Andric     break;
32740b57cec5SDimitry Andric   }
32750b57cec5SDimitry Andric   }
32760b57cec5SDimitry Andric 
32770b57cec5SDimitry Andric   // For 64-bit sequences, the extensions are the same for the GE/LE cases.
32780b57cec5SDimitry Andric   if (!Is32Bit &&
32790b57cec5SDimitry Andric       (CmpTy == ZeroCompare::GEZExt || CmpTy == ZeroCompare::LEZExt))
32800b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
32810b57cec5SDimitry Andric                                           ToExtend, S->getI64Imm(1, dl),
32820b57cec5SDimitry Andric                                           S->getI64Imm(63, dl)), 0);
32830b57cec5SDimitry Andric   if (!Is32Bit &&
32840b57cec5SDimitry Andric       (CmpTy == ZeroCompare::GESExt || CmpTy == ZeroCompare::LESExt))
32850b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, ToExtend,
32860b57cec5SDimitry Andric                                           S->getI64Imm(63, dl)), 0);
32870b57cec5SDimitry Andric 
32880b57cec5SDimitry Andric   assert(Is32Bit && "Should have handled the 32-bit sequences above.");
32890b57cec5SDimitry Andric   // For 32-bit sequences, the extensions differ between GE/LE cases.
32900b57cec5SDimitry Andric   switch (CmpTy) {
32910b57cec5SDimitry Andric   case ZeroCompare::GEZExt: {
32920b57cec5SDimitry Andric     SDValue ShiftOps[] = { ToExtend, S->getI32Imm(1, dl), S->getI32Imm(31, dl),
32930b57cec5SDimitry Andric                            S->getI32Imm(31, dl) };
32940b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32,
32950b57cec5SDimitry Andric                                           ShiftOps), 0);
32960b57cec5SDimitry Andric   }
32970b57cec5SDimitry Andric   case ZeroCompare::GESExt:
32980b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SRAWI, dl, MVT::i32, ToExtend,
32990b57cec5SDimitry Andric                                           S->getI32Imm(31, dl)), 0);
33000b57cec5SDimitry Andric   case ZeroCompare::LEZExt:
33010b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::XORI8, dl, MVT::i64, ToExtend,
33020b57cec5SDimitry Andric                                           S->getI32Imm(1, dl)), 0);
33030b57cec5SDimitry Andric   case ZeroCompare::LESExt:
33040b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, ToExtend,
33050b57cec5SDimitry Andric                                           S->getI32Imm(-1, dl)), 0);
33060b57cec5SDimitry Andric   }
33070b57cec5SDimitry Andric 
33080b57cec5SDimitry Andric   // The above case covers all the enumerators so it can't have a default clause
33090b57cec5SDimitry Andric   // to avoid compiler warnings.
33100b57cec5SDimitry Andric   llvm_unreachable("Unknown zero-comparison type.");
33110b57cec5SDimitry Andric }
33120b57cec5SDimitry Andric 
33130b57cec5SDimitry Andric /// Produces a zero-extended result of comparing two 32-bit values according to
33140b57cec5SDimitry Andric /// the passed condition code.
33150b57cec5SDimitry Andric SDValue
get32BitZExtCompare(SDValue LHS,SDValue RHS,ISD::CondCode CC,int64_t RHSValue,SDLoc dl)33160b57cec5SDimitry Andric IntegerCompareEliminator::get32BitZExtCompare(SDValue LHS, SDValue RHS,
33170b57cec5SDimitry Andric                                               ISD::CondCode CC,
33180b57cec5SDimitry Andric                                               int64_t RHSValue, SDLoc dl) {
33190b57cec5SDimitry Andric   if (CmpInGPR == ICGPR_I64 || CmpInGPR == ICGPR_SextI64 ||
33200b57cec5SDimitry Andric       CmpInGPR == ICGPR_ZextI64 || CmpInGPR == ICGPR_Sext)
33210b57cec5SDimitry Andric     return SDValue();
33220b57cec5SDimitry Andric   bool IsRHSZero = RHSValue == 0;
33230b57cec5SDimitry Andric   bool IsRHSOne = RHSValue == 1;
33240b57cec5SDimitry Andric   bool IsRHSNegOne = RHSValue == -1LL;
33250b57cec5SDimitry Andric   switch (CC) {
33260b57cec5SDimitry Andric   default: return SDValue();
33270b57cec5SDimitry Andric   case ISD::SETEQ: {
33280b57cec5SDimitry Andric     // (zext (setcc %a, %b, seteq)) -> (lshr (cntlzw (xor %a, %b)), 5)
33290b57cec5SDimitry Andric     // (zext (setcc %a, 0, seteq))  -> (lshr (cntlzw %a), 5)
33300b57cec5SDimitry Andric     SDValue Xor = IsRHSZero ? LHS :
33310b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR, dl, MVT::i32, LHS, RHS), 0);
33320b57cec5SDimitry Andric     SDValue Clz =
33330b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::CNTLZW, dl, MVT::i32, Xor), 0);
33340b57cec5SDimitry Andric     SDValue ShiftOps[] = { Clz, S->getI32Imm(27, dl), S->getI32Imm(5, dl),
33350b57cec5SDimitry Andric       S->getI32Imm(31, dl) };
33360b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32,
33370b57cec5SDimitry Andric                                           ShiftOps), 0);
33380b57cec5SDimitry Andric   }
33390b57cec5SDimitry Andric   case ISD::SETNE: {
33400b57cec5SDimitry Andric     // (zext (setcc %a, %b, setne)) -> (xor (lshr (cntlzw (xor %a, %b)), 5), 1)
33410b57cec5SDimitry Andric     // (zext (setcc %a, 0, setne))  -> (xor (lshr (cntlzw %a), 5), 1)
33420b57cec5SDimitry Andric     SDValue Xor = IsRHSZero ? LHS :
33430b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR, dl, MVT::i32, LHS, RHS), 0);
33440b57cec5SDimitry Andric     SDValue Clz =
33450b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::CNTLZW, dl, MVT::i32, Xor), 0);
33460b57cec5SDimitry Andric     SDValue ShiftOps[] = { Clz, S->getI32Imm(27, dl), S->getI32Imm(5, dl),
33470b57cec5SDimitry Andric       S->getI32Imm(31, dl) };
33480b57cec5SDimitry Andric     SDValue Shift =
33490b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, ShiftOps), 0);
33500b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::XORI, dl, MVT::i32, Shift,
33510b57cec5SDimitry Andric                                           S->getI32Imm(1, dl)), 0);
33520b57cec5SDimitry Andric   }
33530b57cec5SDimitry Andric   case ISD::SETGE: {
33540b57cec5SDimitry Andric     // (zext (setcc %a, %b, setge)) -> (xor (lshr (sub %a, %b), 63), 1)
33550b57cec5SDimitry Andric     // (zext (setcc %a, 0, setge))  -> (lshr (~ %a), 31)
33560b57cec5SDimitry Andric     if(IsRHSZero)
33570b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GEZExt);
33580b57cec5SDimitry Andric 
33590b57cec5SDimitry Andric     // Not a special case (i.e. RHS == 0). Handle (%a >= %b) as (%b <= %a)
33600b57cec5SDimitry Andric     // by swapping inputs and falling through.
33610b57cec5SDimitry Andric     std::swap(LHS, RHS);
33620b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3363349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
3364bdd1243dSDimitry Andric     [[fallthrough]];
33650b57cec5SDimitry Andric   }
33660b57cec5SDimitry Andric   case ISD::SETLE: {
33670b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
33680b57cec5SDimitry Andric       return SDValue();
33690b57cec5SDimitry Andric     // (zext (setcc %a, %b, setle)) -> (xor (lshr (sub %b, %a), 63), 1)
33700b57cec5SDimitry Andric     // (zext (setcc %a, 0, setle))  -> (xor (lshr (- %a), 63), 1)
33710b57cec5SDimitry Andric     if(IsRHSZero) {
33720b57cec5SDimitry Andric       if (CmpInGPR == ICGPR_NonExtIn)
33730b57cec5SDimitry Andric         return SDValue();
33740b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LEZExt);
33750b57cec5SDimitry Andric     }
33760b57cec5SDimitry Andric 
33770b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
33780b57cec5SDimitry Andric     LHS = signExtendInputIfNeeded(LHS);
33790b57cec5SDimitry Andric     RHS = signExtendInputIfNeeded(RHS);
33800b57cec5SDimitry Andric     SDValue Sub =
33810b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, LHS, RHS), 0);
33820b57cec5SDimitry Andric     SDValue Shift =
33830b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Sub,
33840b57cec5SDimitry Andric                                      S->getI64Imm(1, dl), S->getI64Imm(63, dl)),
33850b57cec5SDimitry Andric               0);
33860b57cec5SDimitry Andric     return
33870b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XORI8, dl,
33880b57cec5SDimitry Andric                                      MVT::i64, Shift, S->getI32Imm(1, dl)), 0);
33890b57cec5SDimitry Andric   }
33900b57cec5SDimitry Andric   case ISD::SETGT: {
33910b57cec5SDimitry Andric     // (zext (setcc %a, %b, setgt)) -> (lshr (sub %b, %a), 63)
33920b57cec5SDimitry Andric     // (zext (setcc %a, -1, setgt)) -> (lshr (~ %a), 31)
33930b57cec5SDimitry Andric     // (zext (setcc %a, 0, setgt))  -> (lshr (- %a), 63)
33940b57cec5SDimitry Andric     // Handle SETLT -1 (which is equivalent to SETGE 0).
33950b57cec5SDimitry Andric     if (IsRHSNegOne)
33960b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GEZExt);
33970b57cec5SDimitry Andric 
33980b57cec5SDimitry Andric     if (IsRHSZero) {
33990b57cec5SDimitry Andric       if (CmpInGPR == ICGPR_NonExtIn)
34000b57cec5SDimitry Andric         return SDValue();
34010b57cec5SDimitry Andric       // The upper 32-bits of the register can't be undefined for this sequence.
34020b57cec5SDimitry Andric       LHS = signExtendInputIfNeeded(LHS);
34030b57cec5SDimitry Andric       RHS = signExtendInputIfNeeded(RHS);
34040b57cec5SDimitry Andric       SDValue Neg =
34050b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::NEG8, dl, MVT::i64, LHS), 0);
34060b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
34070b57cec5SDimitry Andric                      Neg, S->getI32Imm(1, dl), S->getI32Imm(63, dl)), 0);
34080b57cec5SDimitry Andric     }
34090b57cec5SDimitry Andric     // Not a special case (i.e. RHS == 0 or RHS == -1). Handle (%a > %b) as
34100b57cec5SDimitry Andric     // (%b < %a) by swapping inputs and falling through.
34110b57cec5SDimitry Andric     std::swap(LHS, RHS);
34120b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3413349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
34140b57cec5SDimitry Andric     IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
3415bdd1243dSDimitry Andric     [[fallthrough]];
34160b57cec5SDimitry Andric   }
34170b57cec5SDimitry Andric   case ISD::SETLT: {
34180b57cec5SDimitry Andric     // (zext (setcc %a, %b, setlt)) -> (lshr (sub %a, %b), 63)
34190b57cec5SDimitry Andric     // (zext (setcc %a, 1, setlt))  -> (xor (lshr (- %a), 63), 1)
34200b57cec5SDimitry Andric     // (zext (setcc %a, 0, setlt))  -> (lshr %a, 31)
34210b57cec5SDimitry Andric     // Handle SETLT 1 (which is equivalent to SETLE 0).
34220b57cec5SDimitry Andric     if (IsRHSOne) {
34230b57cec5SDimitry Andric       if (CmpInGPR == ICGPR_NonExtIn)
34240b57cec5SDimitry Andric         return SDValue();
34250b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LEZExt);
34260b57cec5SDimitry Andric     }
34270b57cec5SDimitry Andric 
34280b57cec5SDimitry Andric     if (IsRHSZero) {
34290b57cec5SDimitry Andric       SDValue ShiftOps[] = { LHS, S->getI32Imm(1, dl), S->getI32Imm(31, dl),
34300b57cec5SDimitry Andric                              S->getI32Imm(31, dl) };
34310b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32,
34320b57cec5SDimitry Andric                                             ShiftOps), 0);
34330b57cec5SDimitry Andric     }
34340b57cec5SDimitry Andric 
34350b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
34360b57cec5SDimitry Andric       return SDValue();
34370b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
34380b57cec5SDimitry Andric     LHS = signExtendInputIfNeeded(LHS);
34390b57cec5SDimitry Andric     RHS = signExtendInputIfNeeded(RHS);
34400b57cec5SDimitry Andric     SDValue SUBFNode =
34410b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, RHS, LHS), 0);
34420b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
34430b57cec5SDimitry Andric                                     SUBFNode, S->getI64Imm(1, dl),
34440b57cec5SDimitry Andric                                     S->getI64Imm(63, dl)), 0);
34450b57cec5SDimitry Andric   }
34460b57cec5SDimitry Andric   case ISD::SETUGE:
34470b57cec5SDimitry Andric     // (zext (setcc %a, %b, setuge)) -> (xor (lshr (sub %b, %a), 63), 1)
34480b57cec5SDimitry Andric     // (zext (setcc %a, %b, setule)) -> (xor (lshr (sub %a, %b), 63), 1)
34490b57cec5SDimitry Andric     std::swap(LHS, RHS);
3450bdd1243dSDimitry Andric     [[fallthrough]];
34510b57cec5SDimitry Andric   case ISD::SETULE: {
34520b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
34530b57cec5SDimitry Andric       return SDValue();
34540b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
34550b57cec5SDimitry Andric     LHS = zeroExtendInputIfNeeded(LHS);
34560b57cec5SDimitry Andric     RHS = zeroExtendInputIfNeeded(RHS);
34570b57cec5SDimitry Andric     SDValue Subtract =
34580b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, LHS, RHS), 0);
34590b57cec5SDimitry Andric     SDValue SrdiNode =
34600b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
34610b57cec5SDimitry Andric                                           Subtract, S->getI64Imm(1, dl),
34620b57cec5SDimitry Andric                                           S->getI64Imm(63, dl)), 0);
34630b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::XORI8, dl, MVT::i64, SrdiNode,
34640b57cec5SDimitry Andric                                             S->getI32Imm(1, dl)), 0);
34650b57cec5SDimitry Andric   }
34660b57cec5SDimitry Andric   case ISD::SETUGT:
34670b57cec5SDimitry Andric     // (zext (setcc %a, %b, setugt)) -> (lshr (sub %b, %a), 63)
34680b57cec5SDimitry Andric     // (zext (setcc %a, %b, setult)) -> (lshr (sub %a, %b), 63)
34690b57cec5SDimitry Andric     std::swap(LHS, RHS);
3470bdd1243dSDimitry Andric     [[fallthrough]];
34710b57cec5SDimitry Andric   case ISD::SETULT: {
34720b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
34730b57cec5SDimitry Andric       return SDValue();
34740b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
34750b57cec5SDimitry Andric     LHS = zeroExtendInputIfNeeded(LHS);
34760b57cec5SDimitry Andric     RHS = zeroExtendInputIfNeeded(RHS);
34770b57cec5SDimitry Andric     SDValue Subtract =
34780b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, RHS, LHS), 0);
34790b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
34800b57cec5SDimitry Andric                                           Subtract, S->getI64Imm(1, dl),
34810b57cec5SDimitry Andric                                           S->getI64Imm(63, dl)), 0);
34820b57cec5SDimitry Andric   }
34830b57cec5SDimitry Andric   }
34840b57cec5SDimitry Andric }
34850b57cec5SDimitry Andric 
34860b57cec5SDimitry Andric /// Produces a sign-extended result of comparing two 32-bit values according to
34870b57cec5SDimitry Andric /// the passed condition code.
34880b57cec5SDimitry Andric SDValue
get32BitSExtCompare(SDValue LHS,SDValue RHS,ISD::CondCode CC,int64_t RHSValue,SDLoc dl)34890b57cec5SDimitry Andric IntegerCompareEliminator::get32BitSExtCompare(SDValue LHS, SDValue RHS,
34900b57cec5SDimitry Andric                                               ISD::CondCode CC,
34910b57cec5SDimitry Andric                                               int64_t RHSValue, SDLoc dl) {
34920b57cec5SDimitry Andric   if (CmpInGPR == ICGPR_I64 || CmpInGPR == ICGPR_SextI64 ||
34930b57cec5SDimitry Andric       CmpInGPR == ICGPR_ZextI64 || CmpInGPR == ICGPR_Zext)
34940b57cec5SDimitry Andric     return SDValue();
34950b57cec5SDimitry Andric   bool IsRHSZero = RHSValue == 0;
34960b57cec5SDimitry Andric   bool IsRHSOne = RHSValue == 1;
34970b57cec5SDimitry Andric   bool IsRHSNegOne = RHSValue == -1LL;
34980b57cec5SDimitry Andric 
34990b57cec5SDimitry Andric   switch (CC) {
35000b57cec5SDimitry Andric   default: return SDValue();
35010b57cec5SDimitry Andric   case ISD::SETEQ: {
35020b57cec5SDimitry Andric     // (sext (setcc %a, %b, seteq)) ->
35030b57cec5SDimitry Andric     //   (ashr (shl (ctlz (xor %a, %b)), 58), 63)
35040b57cec5SDimitry Andric     // (sext (setcc %a, 0, seteq)) ->
35050b57cec5SDimitry Andric     //   (ashr (shl (ctlz %a), 58), 63)
35060b57cec5SDimitry Andric     SDValue CountInput = IsRHSZero ? LHS :
35070b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR, dl, MVT::i32, LHS, RHS), 0);
35080b57cec5SDimitry Andric     SDValue Cntlzw =
35090b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::CNTLZW, dl, MVT::i32, CountInput), 0);
35100b57cec5SDimitry Andric     SDValue SHLOps[] = { Cntlzw, S->getI32Imm(27, dl),
35110b57cec5SDimitry Andric                          S->getI32Imm(5, dl), S->getI32Imm(31, dl) };
35120b57cec5SDimitry Andric     SDValue Slwi =
35130b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, SHLOps), 0);
35140b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::NEG, dl, MVT::i32, Slwi), 0);
35150b57cec5SDimitry Andric   }
35160b57cec5SDimitry Andric   case ISD::SETNE: {
35170b57cec5SDimitry Andric     // Bitwise xor the operands, count leading zeros, shift right by 5 bits and
35180b57cec5SDimitry Andric     // flip the bit, finally take 2's complement.
35190b57cec5SDimitry Andric     // (sext (setcc %a, %b, setne)) ->
35200b57cec5SDimitry Andric     //   (neg (xor (lshr (ctlz (xor %a, %b)), 5), 1))
35210b57cec5SDimitry Andric     // Same as above, but the first xor is not needed.
35220b57cec5SDimitry Andric     // (sext (setcc %a, 0, setne)) ->
35230b57cec5SDimitry Andric     //   (neg (xor (lshr (ctlz %a), 5), 1))
35240b57cec5SDimitry Andric     SDValue Xor = IsRHSZero ? LHS :
35250b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR, dl, MVT::i32, LHS, RHS), 0);
35260b57cec5SDimitry Andric     SDValue Clz =
35270b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::CNTLZW, dl, MVT::i32, Xor), 0);
35280b57cec5SDimitry Andric     SDValue ShiftOps[] =
35290b57cec5SDimitry Andric       { Clz, S->getI32Imm(27, dl), S->getI32Imm(5, dl), S->getI32Imm(31, dl) };
35300b57cec5SDimitry Andric     SDValue Shift =
35310b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, ShiftOps), 0);
35320b57cec5SDimitry Andric     SDValue Xori =
35330b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XORI, dl, MVT::i32, Shift,
35340b57cec5SDimitry Andric                                      S->getI32Imm(1, dl)), 0);
35350b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::NEG, dl, MVT::i32, Xori), 0);
35360b57cec5SDimitry Andric   }
35370b57cec5SDimitry Andric   case ISD::SETGE: {
35380b57cec5SDimitry Andric     // (sext (setcc %a, %b, setge)) -> (add (lshr (sub %a, %b), 63), -1)
35390b57cec5SDimitry Andric     // (sext (setcc %a, 0, setge))  -> (ashr (~ %a), 31)
35400b57cec5SDimitry Andric     if (IsRHSZero)
35410b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GESExt);
35420b57cec5SDimitry Andric 
35430b57cec5SDimitry Andric     // Not a special case (i.e. RHS == 0). Handle (%a >= %b) as (%b <= %a)
35440b57cec5SDimitry Andric     // by swapping inputs and falling through.
35450b57cec5SDimitry Andric     std::swap(LHS, RHS);
35460b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3547349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
3548bdd1243dSDimitry Andric     [[fallthrough]];
35490b57cec5SDimitry Andric   }
35500b57cec5SDimitry Andric   case ISD::SETLE: {
35510b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
35520b57cec5SDimitry Andric       return SDValue();
35530b57cec5SDimitry Andric     // (sext (setcc %a, %b, setge)) -> (add (lshr (sub %b, %a), 63), -1)
35540b57cec5SDimitry Andric     // (sext (setcc %a, 0, setle))  -> (add (lshr (- %a), 63), -1)
35550b57cec5SDimitry Andric     if (IsRHSZero)
35560b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LESExt);
35570b57cec5SDimitry Andric 
35580b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
35590b57cec5SDimitry Andric     LHS = signExtendInputIfNeeded(LHS);
35600b57cec5SDimitry Andric     RHS = signExtendInputIfNeeded(RHS);
35610b57cec5SDimitry Andric     SDValue SUBFNode =
35620b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, MVT::Glue,
35630b57cec5SDimitry Andric                                      LHS, RHS), 0);
35640b57cec5SDimitry Andric     SDValue Srdi =
35650b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
35660b57cec5SDimitry Andric                                      SUBFNode, S->getI64Imm(1, dl),
35670b57cec5SDimitry Andric                                      S->getI64Imm(63, dl)), 0);
35680b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, Srdi,
35690b57cec5SDimitry Andric                                           S->getI32Imm(-1, dl)), 0);
35700b57cec5SDimitry Andric   }
35710b57cec5SDimitry Andric   case ISD::SETGT: {
35720b57cec5SDimitry Andric     // (sext (setcc %a, %b, setgt)) -> (ashr (sub %b, %a), 63)
35730b57cec5SDimitry Andric     // (sext (setcc %a, -1, setgt)) -> (ashr (~ %a), 31)
35740b57cec5SDimitry Andric     // (sext (setcc %a, 0, setgt))  -> (ashr (- %a), 63)
35750b57cec5SDimitry Andric     if (IsRHSNegOne)
35760b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GESExt);
35770b57cec5SDimitry Andric     if (IsRHSZero) {
35780b57cec5SDimitry Andric       if (CmpInGPR == ICGPR_NonExtIn)
35790b57cec5SDimitry Andric         return SDValue();
35800b57cec5SDimitry Andric       // The upper 32-bits of the register can't be undefined for this sequence.
35810b57cec5SDimitry Andric       LHS = signExtendInputIfNeeded(LHS);
35820b57cec5SDimitry Andric       RHS = signExtendInputIfNeeded(RHS);
35830b57cec5SDimitry Andric       SDValue Neg =
35840b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::NEG8, dl, MVT::i64, LHS), 0);
35850b57cec5SDimitry Andric         return SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, Neg,
35860b57cec5SDimitry Andric                                               S->getI64Imm(63, dl)), 0);
35870b57cec5SDimitry Andric     }
35880b57cec5SDimitry Andric     // Not a special case (i.e. RHS == 0 or RHS == -1). Handle (%a > %b) as
35890b57cec5SDimitry Andric     // (%b < %a) by swapping inputs and falling through.
35900b57cec5SDimitry Andric     std::swap(LHS, RHS);
35910b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3592349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
35930b57cec5SDimitry Andric     IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
3594bdd1243dSDimitry Andric     [[fallthrough]];
35950b57cec5SDimitry Andric   }
35960b57cec5SDimitry Andric   case ISD::SETLT: {
35970b57cec5SDimitry Andric     // (sext (setcc %a, %b, setgt)) -> (ashr (sub %a, %b), 63)
35980b57cec5SDimitry Andric     // (sext (setcc %a, 1, setgt))  -> (add (lshr (- %a), 63), -1)
35990b57cec5SDimitry Andric     // (sext (setcc %a, 0, setgt))  -> (ashr %a, 31)
36000b57cec5SDimitry Andric     if (IsRHSOne) {
36010b57cec5SDimitry Andric       if (CmpInGPR == ICGPR_NonExtIn)
36020b57cec5SDimitry Andric         return SDValue();
36030b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LESExt);
36040b57cec5SDimitry Andric     }
36050b57cec5SDimitry Andric     if (IsRHSZero)
36060b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::SRAWI, dl, MVT::i32, LHS,
36070b57cec5SDimitry Andric                                             S->getI32Imm(31, dl)), 0);
36080b57cec5SDimitry Andric 
36090b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
36100b57cec5SDimitry Andric       return SDValue();
36110b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
36120b57cec5SDimitry Andric     LHS = signExtendInputIfNeeded(LHS);
36130b57cec5SDimitry Andric     RHS = signExtendInputIfNeeded(RHS);
36140b57cec5SDimitry Andric     SDValue SUBFNode =
36150b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, RHS, LHS), 0);
36160b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64,
36170b57cec5SDimitry Andric                                           SUBFNode, S->getI64Imm(63, dl)), 0);
36180b57cec5SDimitry Andric   }
36190b57cec5SDimitry Andric   case ISD::SETUGE:
36200b57cec5SDimitry Andric     // (sext (setcc %a, %b, setuge)) -> (add (lshr (sub %a, %b), 63), -1)
36210b57cec5SDimitry Andric     // (sext (setcc %a, %b, setule)) -> (add (lshr (sub %b, %a), 63), -1)
36220b57cec5SDimitry Andric     std::swap(LHS, RHS);
3623bdd1243dSDimitry Andric     [[fallthrough]];
36240b57cec5SDimitry Andric   case ISD::SETULE: {
36250b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
36260b57cec5SDimitry Andric       return SDValue();
36270b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
36280b57cec5SDimitry Andric     LHS = zeroExtendInputIfNeeded(LHS);
36290b57cec5SDimitry Andric     RHS = zeroExtendInputIfNeeded(RHS);
36300b57cec5SDimitry Andric     SDValue Subtract =
36310b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, LHS, RHS), 0);
36320b57cec5SDimitry Andric     SDValue Shift =
36330b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Subtract,
36340b57cec5SDimitry Andric                                      S->getI32Imm(1, dl), S->getI32Imm(63,dl)),
36350b57cec5SDimitry Andric               0);
36360b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, Shift,
36370b57cec5SDimitry Andric                                           S->getI32Imm(-1, dl)), 0);
36380b57cec5SDimitry Andric   }
36390b57cec5SDimitry Andric   case ISD::SETUGT:
36400b57cec5SDimitry Andric     // (sext (setcc %a, %b, setugt)) -> (ashr (sub %b, %a), 63)
36410b57cec5SDimitry Andric     // (sext (setcc %a, %b, setugt)) -> (ashr (sub %a, %b), 63)
36420b57cec5SDimitry Andric     std::swap(LHS, RHS);
3643bdd1243dSDimitry Andric     [[fallthrough]];
36440b57cec5SDimitry Andric   case ISD::SETULT: {
36450b57cec5SDimitry Andric     if (CmpInGPR == ICGPR_NonExtIn)
36460b57cec5SDimitry Andric       return SDValue();
36470b57cec5SDimitry Andric     // The upper 32-bits of the register can't be undefined for this sequence.
36480b57cec5SDimitry Andric     LHS = zeroExtendInputIfNeeded(LHS);
36490b57cec5SDimitry Andric     RHS = zeroExtendInputIfNeeded(RHS);
36500b57cec5SDimitry Andric     SDValue Subtract =
36510b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, RHS, LHS), 0);
36520b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64,
36530b57cec5SDimitry Andric                                           Subtract, S->getI64Imm(63, dl)), 0);
36540b57cec5SDimitry Andric   }
36550b57cec5SDimitry Andric   }
36560b57cec5SDimitry Andric }
36570b57cec5SDimitry Andric 
36580b57cec5SDimitry Andric /// Produces a zero-extended result of comparing two 64-bit values according to
36590b57cec5SDimitry Andric /// the passed condition code.
36600b57cec5SDimitry Andric SDValue
get64BitZExtCompare(SDValue LHS,SDValue RHS,ISD::CondCode CC,int64_t RHSValue,SDLoc dl)36610b57cec5SDimitry Andric IntegerCompareEliminator::get64BitZExtCompare(SDValue LHS, SDValue RHS,
36620b57cec5SDimitry Andric                                               ISD::CondCode CC,
36630b57cec5SDimitry Andric                                               int64_t RHSValue, SDLoc dl) {
36640b57cec5SDimitry Andric   if (CmpInGPR == ICGPR_I32 || CmpInGPR == ICGPR_SextI32 ||
36650b57cec5SDimitry Andric       CmpInGPR == ICGPR_ZextI32 || CmpInGPR == ICGPR_Sext)
36660b57cec5SDimitry Andric     return SDValue();
36670b57cec5SDimitry Andric   bool IsRHSZero = RHSValue == 0;
36680b57cec5SDimitry Andric   bool IsRHSOne = RHSValue == 1;
36690b57cec5SDimitry Andric   bool IsRHSNegOne = RHSValue == -1LL;
36700b57cec5SDimitry Andric   switch (CC) {
36710b57cec5SDimitry Andric   default: return SDValue();
36720b57cec5SDimitry Andric   case ISD::SETEQ: {
36730b57cec5SDimitry Andric     // (zext (setcc %a, %b, seteq)) -> (lshr (ctlz (xor %a, %b)), 6)
36740b57cec5SDimitry Andric     // (zext (setcc %a, 0, seteq)) ->  (lshr (ctlz %a), 6)
36750b57cec5SDimitry Andric     SDValue Xor = IsRHSZero ? LHS :
36760b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
36770b57cec5SDimitry Andric     SDValue Clz =
36780b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::CNTLZD, dl, MVT::i64, Xor), 0);
36790b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Clz,
36800b57cec5SDimitry Andric                                           S->getI64Imm(58, dl),
36810b57cec5SDimitry Andric                                           S->getI64Imm(63, dl)), 0);
36820b57cec5SDimitry Andric   }
36830b57cec5SDimitry Andric   case ISD::SETNE: {
36840b57cec5SDimitry Andric     // {addc.reg, addc.CA} = (addcarry (xor %a, %b), -1)
36850b57cec5SDimitry Andric     // (zext (setcc %a, %b, setne)) -> (sube addc.reg, addc.reg, addc.CA)
36860b57cec5SDimitry Andric     // {addcz.reg, addcz.CA} = (addcarry %a, -1)
36870b57cec5SDimitry Andric     // (zext (setcc %a, 0, setne)) -> (sube addcz.reg, addcz.reg, addcz.CA)
36880b57cec5SDimitry Andric     SDValue Xor = IsRHSZero ? LHS :
36890b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
36900b57cec5SDimitry Andric     SDValue AC =
36910b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::ADDIC8, dl, MVT::i64, MVT::Glue,
36920b57cec5SDimitry Andric                                      Xor, S->getI32Imm(~0U, dl)), 0);
36930b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, AC,
36940b57cec5SDimitry Andric                                           Xor, AC.getValue(1)), 0);
36950b57cec5SDimitry Andric   }
36960b57cec5SDimitry Andric   case ISD::SETGE: {
36970b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
36980b57cec5SDimitry Andric     // (zext (setcc %a, %b, setge)) ->
36990b57cec5SDimitry Andric     //   (adde (lshr %b, 63), (ashr %a, 63), subc.CA)
37000b57cec5SDimitry Andric     // (zext (setcc %a, 0, setge)) -> (lshr (~ %a), 63)
37010b57cec5SDimitry Andric     if (IsRHSZero)
37020b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GEZExt);
37030b57cec5SDimitry Andric     std::swap(LHS, RHS);
37040b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3705349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
3706bdd1243dSDimitry Andric     [[fallthrough]];
37070b57cec5SDimitry Andric   }
37080b57cec5SDimitry Andric   case ISD::SETLE: {
37090b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
37100b57cec5SDimitry Andric     // (zext (setcc %a, %b, setge)) ->
37110b57cec5SDimitry Andric     //   (adde (lshr %a, 63), (ashr %b, 63), subc.CA)
37120b57cec5SDimitry Andric     // (zext (setcc %a, 0, setge)) -> (lshr (or %a, (add %a, -1)), 63)
37130b57cec5SDimitry Andric     if (IsRHSZero)
37140b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LEZExt);
37150b57cec5SDimitry Andric     SDValue ShiftL =
37160b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, LHS,
37170b57cec5SDimitry Andric                                      S->getI64Imm(1, dl),
37180b57cec5SDimitry Andric                                      S->getI64Imm(63, dl)), 0);
37190b57cec5SDimitry Andric     SDValue ShiftR =
37200b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, RHS,
37210b57cec5SDimitry Andric                                      S->getI64Imm(63, dl)), 0);
37220b57cec5SDimitry Andric     SDValue SubtractCarry =
37230b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
37240b57cec5SDimitry Andric                                      LHS, RHS), 1);
37250b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::ADDE8, dl, MVT::i64, MVT::Glue,
37260b57cec5SDimitry Andric                                           ShiftR, ShiftL, SubtractCarry), 0);
37270b57cec5SDimitry Andric   }
37280b57cec5SDimitry Andric   case ISD::SETGT: {
37290b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
37300b57cec5SDimitry Andric     // (zext (setcc %a, %b, setgt)) ->
37310b57cec5SDimitry Andric     //   (xor (adde (lshr %a, 63), (ashr %b, 63), subc.CA), 1)
37320b57cec5SDimitry Andric     // (zext (setcc %a, 0, setgt)) -> (lshr (nor (add %a, -1), %a), 63)
37330b57cec5SDimitry Andric     if (IsRHSNegOne)
37340b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GEZExt);
37350b57cec5SDimitry Andric     if (IsRHSZero) {
37360b57cec5SDimitry Andric       SDValue Addi =
37370b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, LHS,
37380b57cec5SDimitry Andric                                        S->getI64Imm(~0ULL, dl)), 0);
37390b57cec5SDimitry Andric       SDValue Nor =
37400b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::NOR8, dl, MVT::i64, Addi, LHS), 0);
37410b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Nor,
37420b57cec5SDimitry Andric                                             S->getI64Imm(1, dl),
37430b57cec5SDimitry Andric                                             S->getI64Imm(63, dl)), 0);
37440b57cec5SDimitry Andric     }
37450b57cec5SDimitry Andric     std::swap(LHS, RHS);
37460b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3747349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
37480b57cec5SDimitry Andric     IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
3749bdd1243dSDimitry Andric     [[fallthrough]];
37500b57cec5SDimitry Andric   }
37510b57cec5SDimitry Andric   case ISD::SETLT: {
37520b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
37530b57cec5SDimitry Andric     // (zext (setcc %a, %b, setlt)) ->
37540b57cec5SDimitry Andric     //   (xor (adde (lshr %b, 63), (ashr %a, 63), subc.CA), 1)
37550b57cec5SDimitry Andric     // (zext (setcc %a, 0, setlt)) -> (lshr %a, 63)
37560b57cec5SDimitry Andric     if (IsRHSOne)
37570b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LEZExt);
37580b57cec5SDimitry Andric     if (IsRHSZero)
37590b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, LHS,
37600b57cec5SDimitry Andric                                             S->getI64Imm(1, dl),
37610b57cec5SDimitry Andric                                             S->getI64Imm(63, dl)), 0);
37620b57cec5SDimitry Andric     SDValue SRADINode =
37630b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64,
37640b57cec5SDimitry Andric                                      LHS, S->getI64Imm(63, dl)), 0);
37650b57cec5SDimitry Andric     SDValue SRDINode =
37660b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
37670b57cec5SDimitry Andric                                      RHS, S->getI64Imm(1, dl),
37680b57cec5SDimitry Andric                                      S->getI64Imm(63, dl)), 0);
37690b57cec5SDimitry Andric     SDValue SUBFC8Carry =
37700b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
37710b57cec5SDimitry Andric                                      RHS, LHS), 1);
37720b57cec5SDimitry Andric     SDValue ADDE8Node =
37730b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::ADDE8, dl, MVT::i64, MVT::Glue,
37740b57cec5SDimitry Andric                                      SRDINode, SRADINode, SUBFC8Carry), 0);
37750b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::XORI8, dl, MVT::i64,
37760b57cec5SDimitry Andric                                           ADDE8Node, S->getI64Imm(1, dl)), 0);
37770b57cec5SDimitry Andric   }
37780b57cec5SDimitry Andric   case ISD::SETUGE:
37790b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
37800b57cec5SDimitry Andric     // (zext (setcc %a, %b, setuge)) -> (add (sube %b, %b, subc.CA), 1)
37810b57cec5SDimitry Andric     std::swap(LHS, RHS);
3782bdd1243dSDimitry Andric     [[fallthrough]];
37830b57cec5SDimitry Andric   case ISD::SETULE: {
37840b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
37850b57cec5SDimitry Andric     // (zext (setcc %a, %b, setule)) -> (add (sube %a, %a, subc.CA), 1)
37860b57cec5SDimitry Andric     SDValue SUBFC8Carry =
37870b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
37880b57cec5SDimitry Andric                                      LHS, RHS), 1);
37890b57cec5SDimitry Andric     SDValue SUBFE8Node =
37900b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, MVT::Glue,
37910b57cec5SDimitry Andric                                      LHS, LHS, SUBFC8Carry), 0);
37920b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64,
37930b57cec5SDimitry Andric                                           SUBFE8Node, S->getI64Imm(1, dl)), 0);
37940b57cec5SDimitry Andric   }
37950b57cec5SDimitry Andric   case ISD::SETUGT:
37960b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
37970b57cec5SDimitry Andric     // (zext (setcc %a, %b, setugt)) -> -(sube %b, %b, subc.CA)
37980b57cec5SDimitry Andric     std::swap(LHS, RHS);
3799bdd1243dSDimitry Andric     [[fallthrough]];
38000b57cec5SDimitry Andric   case ISD::SETULT: {
38010b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
38020b57cec5SDimitry Andric     // (zext (setcc %a, %b, setult)) -> -(sube %a, %a, subc.CA)
38030b57cec5SDimitry Andric     SDValue SubtractCarry =
38040b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
38050b57cec5SDimitry Andric                                      RHS, LHS), 1);
38060b57cec5SDimitry Andric     SDValue ExtSub =
38070b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64,
38080b57cec5SDimitry Andric                                      LHS, LHS, SubtractCarry), 0);
38090b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::NEG8, dl, MVT::i64,
38100b57cec5SDimitry Andric                                           ExtSub), 0);
38110b57cec5SDimitry Andric   }
38120b57cec5SDimitry Andric   }
38130b57cec5SDimitry Andric }
38140b57cec5SDimitry Andric 
38150b57cec5SDimitry Andric /// Produces a sign-extended result of comparing two 64-bit values according to
38160b57cec5SDimitry Andric /// the passed condition code.
38170b57cec5SDimitry Andric SDValue
get64BitSExtCompare(SDValue LHS,SDValue RHS,ISD::CondCode CC,int64_t RHSValue,SDLoc dl)38180b57cec5SDimitry Andric IntegerCompareEliminator::get64BitSExtCompare(SDValue LHS, SDValue RHS,
38190b57cec5SDimitry Andric                                               ISD::CondCode CC,
38200b57cec5SDimitry Andric                                               int64_t RHSValue, SDLoc dl) {
38210b57cec5SDimitry Andric   if (CmpInGPR == ICGPR_I32 || CmpInGPR == ICGPR_SextI32 ||
38220b57cec5SDimitry Andric       CmpInGPR == ICGPR_ZextI32 || CmpInGPR == ICGPR_Zext)
38230b57cec5SDimitry Andric     return SDValue();
38240b57cec5SDimitry Andric   bool IsRHSZero = RHSValue == 0;
38250b57cec5SDimitry Andric   bool IsRHSOne = RHSValue == 1;
38260b57cec5SDimitry Andric   bool IsRHSNegOne = RHSValue == -1LL;
38270b57cec5SDimitry Andric   switch (CC) {
38280b57cec5SDimitry Andric   default: return SDValue();
38290b57cec5SDimitry Andric   case ISD::SETEQ: {
38300b57cec5SDimitry Andric     // {addc.reg, addc.CA} = (addcarry (xor %a, %b), -1)
38310b57cec5SDimitry Andric     // (sext (setcc %a, %b, seteq)) -> (sube addc.reg, addc.reg, addc.CA)
38320b57cec5SDimitry Andric     // {addcz.reg, addcz.CA} = (addcarry %a, -1)
38330b57cec5SDimitry Andric     // (sext (setcc %a, 0, seteq)) -> (sube addcz.reg, addcz.reg, addcz.CA)
38340b57cec5SDimitry Andric     SDValue AddInput = IsRHSZero ? LHS :
38350b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
38360b57cec5SDimitry Andric     SDValue Addic =
38370b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::ADDIC8, dl, MVT::i64, MVT::Glue,
38380b57cec5SDimitry Andric                                      AddInput, S->getI32Imm(~0U, dl)), 0);
38390b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, Addic,
38400b57cec5SDimitry Andric                                           Addic, Addic.getValue(1)), 0);
38410b57cec5SDimitry Andric   }
38420b57cec5SDimitry Andric   case ISD::SETNE: {
38430b57cec5SDimitry Andric     // {subfc.reg, subfc.CA} = (subcarry 0, (xor %a, %b))
38440b57cec5SDimitry Andric     // (sext (setcc %a, %b, setne)) -> (sube subfc.reg, subfc.reg, subfc.CA)
38450b57cec5SDimitry Andric     // {subfcz.reg, subfcz.CA} = (subcarry 0, %a)
38460b57cec5SDimitry Andric     // (sext (setcc %a, 0, setne)) -> (sube subfcz.reg, subfcz.reg, subfcz.CA)
38470b57cec5SDimitry Andric     SDValue Xor = IsRHSZero ? LHS :
38480b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
38490b57cec5SDimitry Andric     SDValue SC =
38500b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFIC8, dl, MVT::i64, MVT::Glue,
38510b57cec5SDimitry Andric                                      Xor, S->getI32Imm(0, dl)), 0);
38520b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, SC,
38530b57cec5SDimitry Andric                                           SC, SC.getValue(1)), 0);
38540b57cec5SDimitry Andric   }
38550b57cec5SDimitry Andric   case ISD::SETGE: {
38560b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
38570b57cec5SDimitry Andric     // (zext (setcc %a, %b, setge)) ->
38580b57cec5SDimitry Andric     //   (- (adde (lshr %b, 63), (ashr %a, 63), subc.CA))
38590b57cec5SDimitry Andric     // (zext (setcc %a, 0, setge)) -> (~ (ashr %a, 63))
38600b57cec5SDimitry Andric     if (IsRHSZero)
38610b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GESExt);
38620b57cec5SDimitry Andric     std::swap(LHS, RHS);
38630b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3864349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
3865bdd1243dSDimitry Andric     [[fallthrough]];
38660b57cec5SDimitry Andric   }
38670b57cec5SDimitry Andric   case ISD::SETLE: {
38680b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
38690b57cec5SDimitry Andric     // (zext (setcc %a, %b, setge)) ->
38700b57cec5SDimitry Andric     //   (- (adde (lshr %a, 63), (ashr %b, 63), subc.CA))
38710b57cec5SDimitry Andric     // (zext (setcc %a, 0, setge)) -> (ashr (or %a, (add %a, -1)), 63)
38720b57cec5SDimitry Andric     if (IsRHSZero)
38730b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LESExt);
38740b57cec5SDimitry Andric     SDValue ShiftR =
38750b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, RHS,
38760b57cec5SDimitry Andric                                      S->getI64Imm(63, dl)), 0);
38770b57cec5SDimitry Andric     SDValue ShiftL =
38780b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, LHS,
38790b57cec5SDimitry Andric                                      S->getI64Imm(1, dl),
38800b57cec5SDimitry Andric                                      S->getI64Imm(63, dl)), 0);
38810b57cec5SDimitry Andric     SDValue SubtractCarry =
38820b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
38830b57cec5SDimitry Andric                                      LHS, RHS), 1);
38840b57cec5SDimitry Andric     SDValue Adde =
38850b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::ADDE8, dl, MVT::i64, MVT::Glue,
38860b57cec5SDimitry Andric                                      ShiftR, ShiftL, SubtractCarry), 0);
38870b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::NEG8, dl, MVT::i64, Adde), 0);
38880b57cec5SDimitry Andric   }
38890b57cec5SDimitry Andric   case ISD::SETGT: {
38900b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
38910b57cec5SDimitry Andric     // (zext (setcc %a, %b, setgt)) ->
38920b57cec5SDimitry Andric     //   -(xor (adde (lshr %a, 63), (ashr %b, 63), subc.CA), 1)
38930b57cec5SDimitry Andric     // (zext (setcc %a, 0, setgt)) -> (ashr (nor (add %a, -1), %a), 63)
38940b57cec5SDimitry Andric     if (IsRHSNegOne)
38950b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::GESExt);
38960b57cec5SDimitry Andric     if (IsRHSZero) {
38970b57cec5SDimitry Andric       SDValue Add =
38980b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::ADDI8, dl, MVT::i64, LHS,
38990b57cec5SDimitry Andric                                        S->getI64Imm(-1, dl)), 0);
39000b57cec5SDimitry Andric       SDValue Nor =
39010b57cec5SDimitry Andric         SDValue(CurDAG->getMachineNode(PPC::NOR8, dl, MVT::i64, Add, LHS), 0);
39020b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, Nor,
39030b57cec5SDimitry Andric                                             S->getI64Imm(63, dl)), 0);
39040b57cec5SDimitry Andric     }
39050b57cec5SDimitry Andric     std::swap(LHS, RHS);
39060b57cec5SDimitry Andric     ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
3907349cc55cSDimitry Andric     IsRHSZero = RHSConst && RHSConst->isZero();
39080b57cec5SDimitry Andric     IsRHSOne = RHSConst && RHSConst->getSExtValue() == 1;
3909bdd1243dSDimitry Andric     [[fallthrough]];
39100b57cec5SDimitry Andric   }
39110b57cec5SDimitry Andric   case ISD::SETLT: {
39120b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
39130b57cec5SDimitry Andric     // (zext (setcc %a, %b, setlt)) ->
39140b57cec5SDimitry Andric     //   -(xor (adde (lshr %b, 63), (ashr %a, 63), subc.CA), 1)
39150b57cec5SDimitry Andric     // (zext (setcc %a, 0, setlt)) -> (ashr %a, 63)
39160b57cec5SDimitry Andric     if (IsRHSOne)
39170b57cec5SDimitry Andric       return getCompoundZeroComparisonInGPR(LHS, dl, ZeroCompare::LESExt);
39180b57cec5SDimitry Andric     if (IsRHSZero) {
39190b57cec5SDimitry Andric       return SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, LHS,
39200b57cec5SDimitry Andric                                             S->getI64Imm(63, dl)), 0);
39210b57cec5SDimitry Andric     }
39220b57cec5SDimitry Andric     SDValue SRADINode =
39230b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64,
39240b57cec5SDimitry Andric                                      LHS, S->getI64Imm(63, dl)), 0);
39250b57cec5SDimitry Andric     SDValue SRDINode =
39260b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64,
39270b57cec5SDimitry Andric                                      RHS, S->getI64Imm(1, dl),
39280b57cec5SDimitry Andric                                      S->getI64Imm(63, dl)), 0);
39290b57cec5SDimitry Andric     SDValue SUBFC8Carry =
39300b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
39310b57cec5SDimitry Andric                                      RHS, LHS), 1);
39320b57cec5SDimitry Andric     SDValue ADDE8Node =
39330b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::ADDE8, dl, MVT::i64,
39340b57cec5SDimitry Andric                                      SRDINode, SRADINode, SUBFC8Carry), 0);
39350b57cec5SDimitry Andric     SDValue XORI8Node =
39360b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::XORI8, dl, MVT::i64,
39370b57cec5SDimitry Andric                                      ADDE8Node, S->getI64Imm(1, dl)), 0);
39380b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::NEG8, dl, MVT::i64,
39390b57cec5SDimitry Andric                                           XORI8Node), 0);
39400b57cec5SDimitry Andric   }
39410b57cec5SDimitry Andric   case ISD::SETUGE:
39420b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
39430b57cec5SDimitry Andric     // (sext (setcc %a, %b, setuge)) -> ~(sube %b, %b, subc.CA)
39440b57cec5SDimitry Andric     std::swap(LHS, RHS);
3945bdd1243dSDimitry Andric     [[fallthrough]];
39460b57cec5SDimitry Andric   case ISD::SETULE: {
39470b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
39480b57cec5SDimitry Andric     // (sext (setcc %a, %b, setule)) -> ~(sube %a, %a, subc.CA)
39490b57cec5SDimitry Andric     SDValue SubtractCarry =
39500b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
39510b57cec5SDimitry Andric                                      LHS, RHS), 1);
39520b57cec5SDimitry Andric     SDValue ExtSub =
39530b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, MVT::Glue, LHS,
39540b57cec5SDimitry Andric                                      LHS, SubtractCarry), 0);
39550b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::NOR8, dl, MVT::i64,
39560b57cec5SDimitry Andric                                           ExtSub, ExtSub), 0);
39570b57cec5SDimitry Andric   }
39580b57cec5SDimitry Andric   case ISD::SETUGT:
39590b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %b, %a)
39600b57cec5SDimitry Andric     // (sext (setcc %a, %b, setugt)) -> (sube %b, %b, subc.CA)
39610b57cec5SDimitry Andric     std::swap(LHS, RHS);
3962bdd1243dSDimitry Andric     [[fallthrough]];
39630b57cec5SDimitry Andric   case ISD::SETULT: {
39640b57cec5SDimitry Andric     // {subc.reg, subc.CA} = (subcarry %a, %b)
39650b57cec5SDimitry Andric     // (sext (setcc %a, %b, setult)) -> (sube %a, %a, subc.CA)
39660b57cec5SDimitry Andric     SDValue SubCarry =
39670b57cec5SDimitry Andric       SDValue(CurDAG->getMachineNode(PPC::SUBFC8, dl, MVT::i64, MVT::Glue,
39680b57cec5SDimitry Andric                                      RHS, LHS), 1);
39690b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64,
39700b57cec5SDimitry Andric                                      LHS, LHS, SubCarry), 0);
39710b57cec5SDimitry Andric   }
39720b57cec5SDimitry Andric   }
39730b57cec5SDimitry Andric }
39740b57cec5SDimitry Andric 
39750b57cec5SDimitry Andric /// Do all uses of this SDValue need the result in a GPR?
39760b57cec5SDimitry Andric /// This is meant to be used on values that have type i1 since
39770b57cec5SDimitry Andric /// it is somewhat meaningless to ask if values of other types
39780b57cec5SDimitry Andric /// should be kept in GPR's.
allUsesExtend(SDValue Compare,SelectionDAG * CurDAG)39790b57cec5SDimitry Andric static bool allUsesExtend(SDValue Compare, SelectionDAG *CurDAG) {
39800b57cec5SDimitry Andric   assert(Compare.getOpcode() == ISD::SETCC &&
39810b57cec5SDimitry Andric          "An ISD::SETCC node required here.");
39820b57cec5SDimitry Andric 
39830b57cec5SDimitry Andric   // For values that have a single use, the caller should obviously already have
39840b57cec5SDimitry Andric   // checked if that use is an extending use. We check the other uses here.
39850b57cec5SDimitry Andric   if (Compare.hasOneUse())
39860b57cec5SDimitry Andric     return true;
39870b57cec5SDimitry Andric   // We want the value in a GPR if it is being extended, used for a select, or
39880b57cec5SDimitry Andric   // used in logical operations.
3989bdd1243dSDimitry Andric   for (auto *CompareUse : Compare.getNode()->uses())
39900b57cec5SDimitry Andric     if (CompareUse->getOpcode() != ISD::SIGN_EXTEND &&
39910b57cec5SDimitry Andric         CompareUse->getOpcode() != ISD::ZERO_EXTEND &&
39920b57cec5SDimitry Andric         CompareUse->getOpcode() != ISD::SELECT &&
399306c3fb27SDimitry Andric         !ISD::isBitwiseLogicOp(CompareUse->getOpcode())) {
39940b57cec5SDimitry Andric       OmittedForNonExtendUses++;
39950b57cec5SDimitry Andric       return false;
39960b57cec5SDimitry Andric     }
39970b57cec5SDimitry Andric   return true;
39980b57cec5SDimitry Andric }
39990b57cec5SDimitry Andric 
40000b57cec5SDimitry Andric /// Returns an equivalent of a SETCC node but with the result the same width as
40010b57cec5SDimitry Andric /// the inputs. This can also be used for SELECT_CC if either the true or false
40020b57cec5SDimitry Andric /// values is a power of two while the other is zero.
getSETCCInGPR(SDValue Compare,SetccInGPROpts ConvOpts)40030b57cec5SDimitry Andric SDValue IntegerCompareEliminator::getSETCCInGPR(SDValue Compare,
40040b57cec5SDimitry Andric                                                 SetccInGPROpts ConvOpts) {
40050b57cec5SDimitry Andric   assert((Compare.getOpcode() == ISD::SETCC ||
40060b57cec5SDimitry Andric           Compare.getOpcode() == ISD::SELECT_CC) &&
40070b57cec5SDimitry Andric          "An ISD::SETCC node required here.");
40080b57cec5SDimitry Andric 
40090b57cec5SDimitry Andric   // Don't convert this comparison to a GPR sequence because there are uses
40100b57cec5SDimitry Andric   // of the i1 result (i.e. uses that require the result in the CR).
40110b57cec5SDimitry Andric   if ((Compare.getOpcode() == ISD::SETCC) && !allUsesExtend(Compare, CurDAG))
40120b57cec5SDimitry Andric     return SDValue();
40130b57cec5SDimitry Andric 
40140b57cec5SDimitry Andric   SDValue LHS = Compare.getOperand(0);
40150b57cec5SDimitry Andric   SDValue RHS = Compare.getOperand(1);
40160b57cec5SDimitry Andric 
40170b57cec5SDimitry Andric   // The condition code is operand 2 for SETCC and operand 4 for SELECT_CC.
40180b57cec5SDimitry Andric   int CCOpNum = Compare.getOpcode() == ISD::SELECT_CC ? 4 : 2;
40190b57cec5SDimitry Andric   ISD::CondCode CC =
40200b57cec5SDimitry Andric     cast<CondCodeSDNode>(Compare.getOperand(CCOpNum))->get();
40210b57cec5SDimitry Andric   EVT InputVT = LHS.getValueType();
40220b57cec5SDimitry Andric   if (InputVT != MVT::i32 && InputVT != MVT::i64)
40230b57cec5SDimitry Andric     return SDValue();
40240b57cec5SDimitry Andric 
40250b57cec5SDimitry Andric   if (ConvOpts == SetccInGPROpts::ZExtInvert ||
40260b57cec5SDimitry Andric       ConvOpts == SetccInGPROpts::SExtInvert)
4027480093f4SDimitry Andric     CC = ISD::getSetCCInverse(CC, InputVT);
40280b57cec5SDimitry Andric 
40290b57cec5SDimitry Andric   bool Inputs32Bit = InputVT == MVT::i32;
40300b57cec5SDimitry Andric 
40310b57cec5SDimitry Andric   SDLoc dl(Compare);
40320b57cec5SDimitry Andric   ConstantSDNode *RHSConst = dyn_cast<ConstantSDNode>(RHS);
40330b57cec5SDimitry Andric   int64_t RHSValue = RHSConst ? RHSConst->getSExtValue() : INT64_MAX;
40340b57cec5SDimitry Andric   bool IsSext = ConvOpts == SetccInGPROpts::SExtOrig ||
40350b57cec5SDimitry Andric     ConvOpts == SetccInGPROpts::SExtInvert;
40360b57cec5SDimitry Andric 
40370b57cec5SDimitry Andric   if (IsSext && Inputs32Bit)
40380b57cec5SDimitry Andric     return get32BitSExtCompare(LHS, RHS, CC, RHSValue, dl);
40390b57cec5SDimitry Andric   else if (Inputs32Bit)
40400b57cec5SDimitry Andric     return get32BitZExtCompare(LHS, RHS, CC, RHSValue, dl);
40410b57cec5SDimitry Andric   else if (IsSext)
40420b57cec5SDimitry Andric     return get64BitSExtCompare(LHS, RHS, CC, RHSValue, dl);
40430b57cec5SDimitry Andric   return get64BitZExtCompare(LHS, RHS, CC, RHSValue, dl);
40440b57cec5SDimitry Andric }
40450b57cec5SDimitry Andric 
40460b57cec5SDimitry Andric } // end anonymous namespace
40470b57cec5SDimitry Andric 
tryIntCompareInGPR(SDNode * N)40480b57cec5SDimitry Andric bool PPCDAGToDAGISel::tryIntCompareInGPR(SDNode *N) {
40490b57cec5SDimitry Andric   if (N->getValueType(0) != MVT::i32 &&
40500b57cec5SDimitry Andric       N->getValueType(0) != MVT::i64)
40510b57cec5SDimitry Andric     return false;
40520b57cec5SDimitry Andric 
40530b57cec5SDimitry Andric   // This optimization will emit code that assumes 64-bit registers
40540b57cec5SDimitry Andric   // so we don't want to run it in 32-bit mode. Also don't run it
40550b57cec5SDimitry Andric   // on functions that are not to be optimized.
40565f757f3fSDimitry Andric   if (TM.getOptLevel() == CodeGenOptLevel::None || !TM.isPPC64())
40570b57cec5SDimitry Andric     return false;
40580b57cec5SDimitry Andric 
4059e8d8bef9SDimitry Andric   // For POWER10, it is more profitable to use the set boolean extension
4060e8d8bef9SDimitry Andric   // instructions rather than the integer compare elimination codegen.
4061e8d8bef9SDimitry Andric   // Users can override this via the command line option, `--ppc-gpr-icmps`.
4062e8d8bef9SDimitry Andric   if (!(CmpInGPR.getNumOccurrences() > 0) && Subtarget->isISA3_1())
4063e8d8bef9SDimitry Andric     return false;
4064e8d8bef9SDimitry Andric 
40650b57cec5SDimitry Andric   switch (N->getOpcode()) {
40660b57cec5SDimitry Andric   default: break;
40670b57cec5SDimitry Andric   case ISD::ZERO_EXTEND:
40680b57cec5SDimitry Andric   case ISD::SIGN_EXTEND:
40690b57cec5SDimitry Andric   case ISD::AND:
40700b57cec5SDimitry Andric   case ISD::OR:
40710b57cec5SDimitry Andric   case ISD::XOR: {
40720b57cec5SDimitry Andric     IntegerCompareEliminator ICmpElim(CurDAG, this);
40730b57cec5SDimitry Andric     if (SDNode *New = ICmpElim.Select(N)) {
40740b57cec5SDimitry Andric       ReplaceNode(N, New);
40750b57cec5SDimitry Andric       return true;
40760b57cec5SDimitry Andric     }
40770b57cec5SDimitry Andric   }
40780b57cec5SDimitry Andric   }
40790b57cec5SDimitry Andric   return false;
40800b57cec5SDimitry Andric }
40810b57cec5SDimitry Andric 
tryBitPermutation(SDNode * N)40820b57cec5SDimitry Andric bool PPCDAGToDAGISel::tryBitPermutation(SDNode *N) {
40830b57cec5SDimitry Andric   if (N->getValueType(0) != MVT::i32 &&
40840b57cec5SDimitry Andric       N->getValueType(0) != MVT::i64)
40850b57cec5SDimitry Andric     return false;
40860b57cec5SDimitry Andric 
40870b57cec5SDimitry Andric   if (!UseBitPermRewriter)
40880b57cec5SDimitry Andric     return false;
40890b57cec5SDimitry Andric 
40900b57cec5SDimitry Andric   switch (N->getOpcode()) {
40910b57cec5SDimitry Andric   default: break;
4092bdd1243dSDimitry Andric   case ISD::SRL:
4093bdd1243dSDimitry Andric     // If we are on P10, we have a pattern for 32-bit (srl (bswap r), 16) that
4094bdd1243dSDimitry Andric     // uses the BRH instruction.
4095bdd1243dSDimitry Andric     if (Subtarget->isISA3_1() && N->getValueType(0) == MVT::i32 &&
4096bdd1243dSDimitry Andric         N->getOperand(0).getOpcode() == ISD::BSWAP) {
4097bdd1243dSDimitry Andric       auto &OpRight = N->getOperand(1);
4098bdd1243dSDimitry Andric       ConstantSDNode *SRLConst = dyn_cast<ConstantSDNode>(OpRight);
4099bdd1243dSDimitry Andric       if (SRLConst && SRLConst->getSExtValue() == 16)
4100bdd1243dSDimitry Andric         return false;
4101bdd1243dSDimitry Andric     }
410206c3fb27SDimitry Andric     [[fallthrough]];
41030b57cec5SDimitry Andric   case ISD::ROTL:
41040b57cec5SDimitry Andric   case ISD::SHL:
41050b57cec5SDimitry Andric   case ISD::AND:
41060b57cec5SDimitry Andric   case ISD::OR: {
41070b57cec5SDimitry Andric     BitPermutationSelector BPS(CurDAG);
41080b57cec5SDimitry Andric     if (SDNode *New = BPS.Select(N)) {
41090b57cec5SDimitry Andric       ReplaceNode(N, New);
41100b57cec5SDimitry Andric       return true;
41110b57cec5SDimitry Andric     }
41120b57cec5SDimitry Andric     return false;
41130b57cec5SDimitry Andric   }
41140b57cec5SDimitry Andric   }
41150b57cec5SDimitry Andric 
41160b57cec5SDimitry Andric   return false;
41170b57cec5SDimitry Andric }
41180b57cec5SDimitry Andric 
41190b57cec5SDimitry Andric /// SelectCC - Select a comparison of the specified values with the specified
41200b57cec5SDimitry Andric /// condition code, returning the CR# of the expression.
SelectCC(SDValue LHS,SDValue RHS,ISD::CondCode CC,const SDLoc & dl,SDValue Chain)41210b57cec5SDimitry Andric SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC,
4122e8d8bef9SDimitry Andric                                   const SDLoc &dl, SDValue Chain) {
41230b57cec5SDimitry Andric   // Always select the LHS.
41240b57cec5SDimitry Andric   unsigned Opc;
41250b57cec5SDimitry Andric 
41260b57cec5SDimitry Andric   if (LHS.getValueType() == MVT::i32) {
41270b57cec5SDimitry Andric     unsigned Imm;
41280b57cec5SDimitry Andric     if (CC == ISD::SETEQ || CC == ISD::SETNE) {
41290b57cec5SDimitry Andric       if (isInt32Immediate(RHS, Imm)) {
41300b57cec5SDimitry Andric         // SETEQ/SETNE comparison with 16-bit immediate, fold it.
41310b57cec5SDimitry Andric         if (isUInt<16>(Imm))
41320b57cec5SDimitry Andric           return SDValue(CurDAG->getMachineNode(PPC::CMPLWI, dl, MVT::i32, LHS,
41330b57cec5SDimitry Andric                                                 getI32Imm(Imm & 0xFFFF, dl)),
41340b57cec5SDimitry Andric                          0);
41350b57cec5SDimitry Andric         // If this is a 16-bit signed immediate, fold it.
41360b57cec5SDimitry Andric         if (isInt<16>((int)Imm))
41370b57cec5SDimitry Andric           return SDValue(CurDAG->getMachineNode(PPC::CMPWI, dl, MVT::i32, LHS,
41380b57cec5SDimitry Andric                                                 getI32Imm(Imm & 0xFFFF, dl)),
41390b57cec5SDimitry Andric                          0);
41400b57cec5SDimitry Andric 
41410b57cec5SDimitry Andric         // For non-equality comparisons, the default code would materialize the
41420b57cec5SDimitry Andric         // constant, then compare against it, like this:
41430b57cec5SDimitry Andric         //   lis r2, 4660
41440b57cec5SDimitry Andric         //   ori r2, r2, 22136
41450b57cec5SDimitry Andric         //   cmpw cr0, r3, r2
41460b57cec5SDimitry Andric         // Since we are just comparing for equality, we can emit this instead:
41470b57cec5SDimitry Andric         //   xoris r0,r3,0x1234
41480b57cec5SDimitry Andric         //   cmplwi cr0,r0,0x5678
41490b57cec5SDimitry Andric         //   beq cr0,L6
41500b57cec5SDimitry Andric         SDValue Xor(CurDAG->getMachineNode(PPC::XORIS, dl, MVT::i32, LHS,
41510b57cec5SDimitry Andric                                            getI32Imm(Imm >> 16, dl)), 0);
41520b57cec5SDimitry Andric         return SDValue(CurDAG->getMachineNode(PPC::CMPLWI, dl, MVT::i32, Xor,
41530b57cec5SDimitry Andric                                               getI32Imm(Imm & 0xFFFF, dl)), 0);
41540b57cec5SDimitry Andric       }
41550b57cec5SDimitry Andric       Opc = PPC::CMPLW;
41560b57cec5SDimitry Andric     } else if (ISD::isUnsignedIntSetCC(CC)) {
41570b57cec5SDimitry Andric       if (isInt32Immediate(RHS, Imm) && isUInt<16>(Imm))
41580b57cec5SDimitry Andric         return SDValue(CurDAG->getMachineNode(PPC::CMPLWI, dl, MVT::i32, LHS,
41590b57cec5SDimitry Andric                                               getI32Imm(Imm & 0xFFFF, dl)), 0);
41600b57cec5SDimitry Andric       Opc = PPC::CMPLW;
41610b57cec5SDimitry Andric     } else {
41620b57cec5SDimitry Andric       int16_t SImm;
41630b57cec5SDimitry Andric       if (isIntS16Immediate(RHS, SImm))
41640b57cec5SDimitry Andric         return SDValue(CurDAG->getMachineNode(PPC::CMPWI, dl, MVT::i32, LHS,
41650b57cec5SDimitry Andric                                               getI32Imm((int)SImm & 0xFFFF,
41660b57cec5SDimitry Andric                                                         dl)),
41670b57cec5SDimitry Andric                          0);
41680b57cec5SDimitry Andric       Opc = PPC::CMPW;
41690b57cec5SDimitry Andric     }
41700b57cec5SDimitry Andric   } else if (LHS.getValueType() == MVT::i64) {
41710b57cec5SDimitry Andric     uint64_t Imm;
41720b57cec5SDimitry Andric     if (CC == ISD::SETEQ || CC == ISD::SETNE) {
41730b57cec5SDimitry Andric       if (isInt64Immediate(RHS.getNode(), Imm)) {
41740b57cec5SDimitry Andric         // SETEQ/SETNE comparison with 16-bit immediate, fold it.
41750b57cec5SDimitry Andric         if (isUInt<16>(Imm))
41760b57cec5SDimitry Andric           return SDValue(CurDAG->getMachineNode(PPC::CMPLDI, dl, MVT::i64, LHS,
41770b57cec5SDimitry Andric                                                 getI32Imm(Imm & 0xFFFF, dl)),
41780b57cec5SDimitry Andric                          0);
41790b57cec5SDimitry Andric         // If this is a 16-bit signed immediate, fold it.
41800b57cec5SDimitry Andric         if (isInt<16>(Imm))
41810b57cec5SDimitry Andric           return SDValue(CurDAG->getMachineNode(PPC::CMPDI, dl, MVT::i64, LHS,
41820b57cec5SDimitry Andric                                                 getI32Imm(Imm & 0xFFFF, dl)),
41830b57cec5SDimitry Andric                          0);
41840b57cec5SDimitry Andric 
41850b57cec5SDimitry Andric         // For non-equality comparisons, the default code would materialize the
41860b57cec5SDimitry Andric         // constant, then compare against it, like this:
41870b57cec5SDimitry Andric         //   lis r2, 4660
41880b57cec5SDimitry Andric         //   ori r2, r2, 22136
41890b57cec5SDimitry Andric         //   cmpd cr0, r3, r2
41900b57cec5SDimitry Andric         // Since we are just comparing for equality, we can emit this instead:
41910b57cec5SDimitry Andric         //   xoris r0,r3,0x1234
41920b57cec5SDimitry Andric         //   cmpldi cr0,r0,0x5678
41930b57cec5SDimitry Andric         //   beq cr0,L6
41940b57cec5SDimitry Andric         if (isUInt<32>(Imm)) {
41950b57cec5SDimitry Andric           SDValue Xor(CurDAG->getMachineNode(PPC::XORIS8, dl, MVT::i64, LHS,
41960b57cec5SDimitry Andric                                              getI64Imm(Imm >> 16, dl)), 0);
41970b57cec5SDimitry Andric           return SDValue(CurDAG->getMachineNode(PPC::CMPLDI, dl, MVT::i64, Xor,
41980b57cec5SDimitry Andric                                                 getI64Imm(Imm & 0xFFFF, dl)),
41990b57cec5SDimitry Andric                          0);
42000b57cec5SDimitry Andric         }
42010b57cec5SDimitry Andric       }
42020b57cec5SDimitry Andric       Opc = PPC::CMPLD;
42030b57cec5SDimitry Andric     } else if (ISD::isUnsignedIntSetCC(CC)) {
42040b57cec5SDimitry Andric       if (isInt64Immediate(RHS.getNode(), Imm) && isUInt<16>(Imm))
42050b57cec5SDimitry Andric         return SDValue(CurDAG->getMachineNode(PPC::CMPLDI, dl, MVT::i64, LHS,
42060b57cec5SDimitry Andric                                               getI64Imm(Imm & 0xFFFF, dl)), 0);
42070b57cec5SDimitry Andric       Opc = PPC::CMPLD;
42080b57cec5SDimitry Andric     } else {
42090b57cec5SDimitry Andric       int16_t SImm;
42100b57cec5SDimitry Andric       if (isIntS16Immediate(RHS, SImm))
42110b57cec5SDimitry Andric         return SDValue(CurDAG->getMachineNode(PPC::CMPDI, dl, MVT::i64, LHS,
42120b57cec5SDimitry Andric                                               getI64Imm(SImm & 0xFFFF, dl)),
42130b57cec5SDimitry Andric                          0);
42140b57cec5SDimitry Andric       Opc = PPC::CMPD;
42150b57cec5SDimitry Andric     }
42160b57cec5SDimitry Andric   } else if (LHS.getValueType() == MVT::f32) {
42175ffd83dbSDimitry Andric     if (Subtarget->hasSPE()) {
42180b57cec5SDimitry Andric       switch (CC) {
42190b57cec5SDimitry Andric         default:
42200b57cec5SDimitry Andric         case ISD::SETEQ:
42210b57cec5SDimitry Andric         case ISD::SETNE:
42220b57cec5SDimitry Andric           Opc = PPC::EFSCMPEQ;
42230b57cec5SDimitry Andric           break;
42240b57cec5SDimitry Andric         case ISD::SETLT:
42250b57cec5SDimitry Andric         case ISD::SETGE:
42260b57cec5SDimitry Andric         case ISD::SETOLT:
42270b57cec5SDimitry Andric         case ISD::SETOGE:
42280b57cec5SDimitry Andric         case ISD::SETULT:
42290b57cec5SDimitry Andric         case ISD::SETUGE:
42300b57cec5SDimitry Andric           Opc = PPC::EFSCMPLT;
42310b57cec5SDimitry Andric           break;
42320b57cec5SDimitry Andric         case ISD::SETGT:
42330b57cec5SDimitry Andric         case ISD::SETLE:
42340b57cec5SDimitry Andric         case ISD::SETOGT:
42350b57cec5SDimitry Andric         case ISD::SETOLE:
42360b57cec5SDimitry Andric         case ISD::SETUGT:
42370b57cec5SDimitry Andric         case ISD::SETULE:
42380b57cec5SDimitry Andric           Opc = PPC::EFSCMPGT;
42390b57cec5SDimitry Andric           break;
42400b57cec5SDimitry Andric       }
42410b57cec5SDimitry Andric     } else
42420b57cec5SDimitry Andric       Opc = PPC::FCMPUS;
42430b57cec5SDimitry Andric   } else if (LHS.getValueType() == MVT::f64) {
42445ffd83dbSDimitry Andric     if (Subtarget->hasSPE()) {
42450b57cec5SDimitry Andric       switch (CC) {
42460b57cec5SDimitry Andric         default:
42470b57cec5SDimitry Andric         case ISD::SETEQ:
42480b57cec5SDimitry Andric         case ISD::SETNE:
42490b57cec5SDimitry Andric           Opc = PPC::EFDCMPEQ;
42500b57cec5SDimitry Andric           break;
42510b57cec5SDimitry Andric         case ISD::SETLT:
42520b57cec5SDimitry Andric         case ISD::SETGE:
42530b57cec5SDimitry Andric         case ISD::SETOLT:
42540b57cec5SDimitry Andric         case ISD::SETOGE:
42550b57cec5SDimitry Andric         case ISD::SETULT:
42560b57cec5SDimitry Andric         case ISD::SETUGE:
42570b57cec5SDimitry Andric           Opc = PPC::EFDCMPLT;
42580b57cec5SDimitry Andric           break;
42590b57cec5SDimitry Andric         case ISD::SETGT:
42600b57cec5SDimitry Andric         case ISD::SETLE:
42610b57cec5SDimitry Andric         case ISD::SETOGT:
42620b57cec5SDimitry Andric         case ISD::SETOLE:
42630b57cec5SDimitry Andric         case ISD::SETUGT:
42640b57cec5SDimitry Andric         case ISD::SETULE:
42650b57cec5SDimitry Andric           Opc = PPC::EFDCMPGT;
42660b57cec5SDimitry Andric           break;
42670b57cec5SDimitry Andric       }
42680b57cec5SDimitry Andric     } else
42695ffd83dbSDimitry Andric       Opc = Subtarget->hasVSX() ? PPC::XSCMPUDP : PPC::FCMPUD;
42700b57cec5SDimitry Andric   } else {
42710b57cec5SDimitry Andric     assert(LHS.getValueType() == MVT::f128 && "Unknown vt!");
4272fe6060f1SDimitry Andric     assert(Subtarget->hasP9Vector() && "XSCMPUQP requires Power9 Vector");
42730b57cec5SDimitry Andric     Opc = PPC::XSCMPUQP;
42740b57cec5SDimitry Andric   }
4275e8d8bef9SDimitry Andric   if (Chain)
4276e8d8bef9SDimitry Andric     return SDValue(
4277e8d8bef9SDimitry Andric         CurDAG->getMachineNode(Opc, dl, MVT::i32, MVT::Other, LHS, RHS, Chain),
4278e8d8bef9SDimitry Andric         0);
4279e8d8bef9SDimitry Andric   else
42800b57cec5SDimitry Andric     return SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i32, LHS, RHS), 0);
42810b57cec5SDimitry Andric }
42820b57cec5SDimitry Andric 
getPredicateForSetCC(ISD::CondCode CC,const EVT & VT,const PPCSubtarget * Subtarget)4283480093f4SDimitry Andric static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC, const EVT &VT,
4284480093f4SDimitry Andric                                            const PPCSubtarget *Subtarget) {
4285480093f4SDimitry Andric   // For SPE instructions, the result is in GT bit of the CR
4286480093f4SDimitry Andric   bool UseSPE = Subtarget->hasSPE() && VT.isFloatingPoint();
4287480093f4SDimitry Andric 
42880b57cec5SDimitry Andric   switch (CC) {
42890b57cec5SDimitry Andric   case ISD::SETUEQ:
42900b57cec5SDimitry Andric   case ISD::SETONE:
42910b57cec5SDimitry Andric   case ISD::SETOLE:
42920b57cec5SDimitry Andric   case ISD::SETOGE:
42930b57cec5SDimitry Andric     llvm_unreachable("Should be lowered by legalize!");
42940b57cec5SDimitry Andric   default: llvm_unreachable("Unknown condition!");
42950b57cec5SDimitry Andric   case ISD::SETOEQ:
4296480093f4SDimitry Andric   case ISD::SETEQ:
4297480093f4SDimitry Andric     return UseSPE ? PPC::PRED_GT : PPC::PRED_EQ;
42980b57cec5SDimitry Andric   case ISD::SETUNE:
4299480093f4SDimitry Andric   case ISD::SETNE:
4300480093f4SDimitry Andric     return UseSPE ? PPC::PRED_LE : PPC::PRED_NE;
43010b57cec5SDimitry Andric   case ISD::SETOLT:
4302480093f4SDimitry Andric   case ISD::SETLT:
4303480093f4SDimitry Andric     return UseSPE ? PPC::PRED_GT : PPC::PRED_LT;
43040b57cec5SDimitry Andric   case ISD::SETULE:
4305480093f4SDimitry Andric   case ISD::SETLE:
43065ffd83dbSDimitry Andric     return PPC::PRED_LE;
43070b57cec5SDimitry Andric   case ISD::SETOGT:
4308480093f4SDimitry Andric   case ISD::SETGT:
43095ffd83dbSDimitry Andric     return PPC::PRED_GT;
43100b57cec5SDimitry Andric   case ISD::SETUGE:
4311480093f4SDimitry Andric   case ISD::SETGE:
4312480093f4SDimitry Andric     return UseSPE ? PPC::PRED_LE : PPC::PRED_GE;
43130b57cec5SDimitry Andric   case ISD::SETO:   return PPC::PRED_NU;
43140b57cec5SDimitry Andric   case ISD::SETUO:  return PPC::PRED_UN;
43150b57cec5SDimitry Andric     // These two are invalid for floating point.  Assume we have int.
43160b57cec5SDimitry Andric   case ISD::SETULT: return PPC::PRED_LT;
43170b57cec5SDimitry Andric   case ISD::SETUGT: return PPC::PRED_GT;
43180b57cec5SDimitry Andric   }
43190b57cec5SDimitry Andric }
43200b57cec5SDimitry Andric 
43210b57cec5SDimitry Andric /// getCRIdxForSetCC - Return the index of the condition register field
43220b57cec5SDimitry Andric /// associated with the SetCC condition, and whether or not the field is
43230b57cec5SDimitry Andric /// treated as inverted.  That is, lt = 0; ge = 0 inverted.
getCRIdxForSetCC(ISD::CondCode CC,bool & Invert)43240b57cec5SDimitry Andric static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool &Invert) {
43250b57cec5SDimitry Andric   Invert = false;
43260b57cec5SDimitry Andric   switch (CC) {
43270b57cec5SDimitry Andric   default: llvm_unreachable("Unknown condition!");
43280b57cec5SDimitry Andric   case ISD::SETOLT:
43290b57cec5SDimitry Andric   case ISD::SETLT:  return 0;                  // Bit #0 = SETOLT
43300b57cec5SDimitry Andric   case ISD::SETOGT:
43310b57cec5SDimitry Andric   case ISD::SETGT:  return 1;                  // Bit #1 = SETOGT
43320b57cec5SDimitry Andric   case ISD::SETOEQ:
43330b57cec5SDimitry Andric   case ISD::SETEQ:  return 2;                  // Bit #2 = SETOEQ
43340b57cec5SDimitry Andric   case ISD::SETUO:  return 3;                  // Bit #3 = SETUO
43350b57cec5SDimitry Andric   case ISD::SETUGE:
43360b57cec5SDimitry Andric   case ISD::SETGE:  Invert = true; return 0;   // !Bit #0 = SETUGE
43370b57cec5SDimitry Andric   case ISD::SETULE:
43380b57cec5SDimitry Andric   case ISD::SETLE:  Invert = true; return 1;   // !Bit #1 = SETULE
43390b57cec5SDimitry Andric   case ISD::SETUNE:
43400b57cec5SDimitry Andric   case ISD::SETNE:  Invert = true; return 2;   // !Bit #2 = SETUNE
43410b57cec5SDimitry Andric   case ISD::SETO:   Invert = true; return 3;   // !Bit #3 = SETO
43420b57cec5SDimitry Andric   case ISD::SETUEQ:
43430b57cec5SDimitry Andric   case ISD::SETOGE:
43440b57cec5SDimitry Andric   case ISD::SETOLE:
43450b57cec5SDimitry Andric   case ISD::SETONE:
43460b57cec5SDimitry Andric     llvm_unreachable("Invalid branch code: should be expanded by legalize");
43470b57cec5SDimitry Andric   // These are invalid for floating point.  Assume integer.
43480b57cec5SDimitry Andric   case ISD::SETULT: return 0;
43490b57cec5SDimitry Andric   case ISD::SETUGT: return 1;
43500b57cec5SDimitry Andric   }
43510b57cec5SDimitry Andric }
43520b57cec5SDimitry Andric 
43530b57cec5SDimitry Andric // getVCmpInst: return the vector compare instruction for the specified
43540b57cec5SDimitry Andric // vector type and condition code. Since this is for altivec specific code,
4355e8d8bef9SDimitry Andric // only support the altivec types (v16i8, v8i16, v4i32, v2i64, v1i128,
4356e8d8bef9SDimitry Andric // and v4f32).
getVCmpInst(MVT VecVT,ISD::CondCode CC,bool HasVSX,bool & Swap,bool & Negate)43570b57cec5SDimitry Andric static unsigned int getVCmpInst(MVT VecVT, ISD::CondCode CC,
43580b57cec5SDimitry Andric                                 bool HasVSX, bool &Swap, bool &Negate) {
43590b57cec5SDimitry Andric   Swap = false;
43600b57cec5SDimitry Andric   Negate = false;
43610b57cec5SDimitry Andric 
43620b57cec5SDimitry Andric   if (VecVT.isFloatingPoint()) {
43630b57cec5SDimitry Andric     /* Handle some cases by swapping input operands.  */
43640b57cec5SDimitry Andric     switch (CC) {
43650b57cec5SDimitry Andric       case ISD::SETLE: CC = ISD::SETGE; Swap = true; break;
43660b57cec5SDimitry Andric       case ISD::SETLT: CC = ISD::SETGT; Swap = true; break;
43670b57cec5SDimitry Andric       case ISD::SETOLE: CC = ISD::SETOGE; Swap = true; break;
43680b57cec5SDimitry Andric       case ISD::SETOLT: CC = ISD::SETOGT; Swap = true; break;
43690b57cec5SDimitry Andric       case ISD::SETUGE: CC = ISD::SETULE; Swap = true; break;
43700b57cec5SDimitry Andric       case ISD::SETUGT: CC = ISD::SETULT; Swap = true; break;
43710b57cec5SDimitry Andric       default: break;
43720b57cec5SDimitry Andric     }
43730b57cec5SDimitry Andric     /* Handle some cases by negating the result.  */
43740b57cec5SDimitry Andric     switch (CC) {
43750b57cec5SDimitry Andric       case ISD::SETNE: CC = ISD::SETEQ; Negate = true; break;
43760b57cec5SDimitry Andric       case ISD::SETUNE: CC = ISD::SETOEQ; Negate = true; break;
43770b57cec5SDimitry Andric       case ISD::SETULE: CC = ISD::SETOGT; Negate = true; break;
43780b57cec5SDimitry Andric       case ISD::SETULT: CC = ISD::SETOGE; Negate = true; break;
43790b57cec5SDimitry Andric       default: break;
43800b57cec5SDimitry Andric     }
43810b57cec5SDimitry Andric     /* We have instructions implementing the remaining cases.  */
43820b57cec5SDimitry Andric     switch (CC) {
43830b57cec5SDimitry Andric       case ISD::SETEQ:
43840b57cec5SDimitry Andric       case ISD::SETOEQ:
43850b57cec5SDimitry Andric         if (VecVT == MVT::v4f32)
43860b57cec5SDimitry Andric           return HasVSX ? PPC::XVCMPEQSP : PPC::VCMPEQFP;
43870b57cec5SDimitry Andric         else if (VecVT == MVT::v2f64)
43880b57cec5SDimitry Andric           return PPC::XVCMPEQDP;
43890b57cec5SDimitry Andric         break;
43900b57cec5SDimitry Andric       case ISD::SETGT:
43910b57cec5SDimitry Andric       case ISD::SETOGT:
43920b57cec5SDimitry Andric         if (VecVT == MVT::v4f32)
43930b57cec5SDimitry Andric           return HasVSX ? PPC::XVCMPGTSP : PPC::VCMPGTFP;
43940b57cec5SDimitry Andric         else if (VecVT == MVT::v2f64)
43950b57cec5SDimitry Andric           return PPC::XVCMPGTDP;
43960b57cec5SDimitry Andric         break;
43970b57cec5SDimitry Andric       case ISD::SETGE:
43980b57cec5SDimitry Andric       case ISD::SETOGE:
43990b57cec5SDimitry Andric         if (VecVT == MVT::v4f32)
44000b57cec5SDimitry Andric           return HasVSX ? PPC::XVCMPGESP : PPC::VCMPGEFP;
44010b57cec5SDimitry Andric         else if (VecVT == MVT::v2f64)
44020b57cec5SDimitry Andric           return PPC::XVCMPGEDP;
44030b57cec5SDimitry Andric         break;
44040b57cec5SDimitry Andric       default:
44050b57cec5SDimitry Andric         break;
44060b57cec5SDimitry Andric     }
44070b57cec5SDimitry Andric     llvm_unreachable("Invalid floating-point vector compare condition");
44080b57cec5SDimitry Andric   } else {
44090b57cec5SDimitry Andric     /* Handle some cases by swapping input operands.  */
44100b57cec5SDimitry Andric     switch (CC) {
44110b57cec5SDimitry Andric       case ISD::SETGE: CC = ISD::SETLE; Swap = true; break;
44120b57cec5SDimitry Andric       case ISD::SETLT: CC = ISD::SETGT; Swap = true; break;
44130b57cec5SDimitry Andric       case ISD::SETUGE: CC = ISD::SETULE; Swap = true; break;
44140b57cec5SDimitry Andric       case ISD::SETULT: CC = ISD::SETUGT; Swap = true; break;
44150b57cec5SDimitry Andric       default: break;
44160b57cec5SDimitry Andric     }
44170b57cec5SDimitry Andric     /* Handle some cases by negating the result.  */
44180b57cec5SDimitry Andric     switch (CC) {
44190b57cec5SDimitry Andric       case ISD::SETNE: CC = ISD::SETEQ; Negate = true; break;
44200b57cec5SDimitry Andric       case ISD::SETUNE: CC = ISD::SETUEQ; Negate = true; break;
44210b57cec5SDimitry Andric       case ISD::SETLE: CC = ISD::SETGT; Negate = true; break;
44220b57cec5SDimitry Andric       case ISD::SETULE: CC = ISD::SETUGT; Negate = true; break;
44230b57cec5SDimitry Andric       default: break;
44240b57cec5SDimitry Andric     }
44250b57cec5SDimitry Andric     /* We have instructions implementing the remaining cases.  */
44260b57cec5SDimitry Andric     switch (CC) {
44270b57cec5SDimitry Andric       case ISD::SETEQ:
44280b57cec5SDimitry Andric       case ISD::SETUEQ:
44290b57cec5SDimitry Andric         if (VecVT == MVT::v16i8)
44300b57cec5SDimitry Andric           return PPC::VCMPEQUB;
44310b57cec5SDimitry Andric         else if (VecVT == MVT::v8i16)
44320b57cec5SDimitry Andric           return PPC::VCMPEQUH;
44330b57cec5SDimitry Andric         else if (VecVT == MVT::v4i32)
44340b57cec5SDimitry Andric           return PPC::VCMPEQUW;
44350b57cec5SDimitry Andric         else if (VecVT == MVT::v2i64)
44360b57cec5SDimitry Andric           return PPC::VCMPEQUD;
4437e8d8bef9SDimitry Andric         else if (VecVT == MVT::v1i128)
4438e8d8bef9SDimitry Andric           return PPC::VCMPEQUQ;
44390b57cec5SDimitry Andric         break;
44400b57cec5SDimitry Andric       case ISD::SETGT:
44410b57cec5SDimitry Andric         if (VecVT == MVT::v16i8)
44420b57cec5SDimitry Andric           return PPC::VCMPGTSB;
44430b57cec5SDimitry Andric         else if (VecVT == MVT::v8i16)
44440b57cec5SDimitry Andric           return PPC::VCMPGTSH;
44450b57cec5SDimitry Andric         else if (VecVT == MVT::v4i32)
44460b57cec5SDimitry Andric           return PPC::VCMPGTSW;
44470b57cec5SDimitry Andric         else if (VecVT == MVT::v2i64)
44480b57cec5SDimitry Andric           return PPC::VCMPGTSD;
4449e8d8bef9SDimitry Andric         else if (VecVT == MVT::v1i128)
4450e8d8bef9SDimitry Andric            return PPC::VCMPGTSQ;
44510b57cec5SDimitry Andric         break;
44520b57cec5SDimitry Andric       case ISD::SETUGT:
44530b57cec5SDimitry Andric         if (VecVT == MVT::v16i8)
44540b57cec5SDimitry Andric           return PPC::VCMPGTUB;
44550b57cec5SDimitry Andric         else if (VecVT == MVT::v8i16)
44560b57cec5SDimitry Andric           return PPC::VCMPGTUH;
44570b57cec5SDimitry Andric         else if (VecVT == MVT::v4i32)
44580b57cec5SDimitry Andric           return PPC::VCMPGTUW;
44590b57cec5SDimitry Andric         else if (VecVT == MVT::v2i64)
44600b57cec5SDimitry Andric           return PPC::VCMPGTUD;
4461e8d8bef9SDimitry Andric         else if (VecVT == MVT::v1i128)
4462e8d8bef9SDimitry Andric            return PPC::VCMPGTUQ;
44630b57cec5SDimitry Andric         break;
44640b57cec5SDimitry Andric       default:
44650b57cec5SDimitry Andric         break;
44660b57cec5SDimitry Andric     }
44670b57cec5SDimitry Andric     llvm_unreachable("Invalid integer vector compare condition");
44680b57cec5SDimitry Andric   }
44690b57cec5SDimitry Andric }
44700b57cec5SDimitry Andric 
trySETCC(SDNode * N)44710b57cec5SDimitry Andric bool PPCDAGToDAGISel::trySETCC(SDNode *N) {
44720b57cec5SDimitry Andric   SDLoc dl(N);
44730b57cec5SDimitry Andric   unsigned Imm;
4474e8d8bef9SDimitry Andric   bool IsStrict = N->isStrictFPOpcode();
4475e8d8bef9SDimitry Andric   ISD::CondCode CC =
4476e8d8bef9SDimitry Andric       cast<CondCodeSDNode>(N->getOperand(IsStrict ? 3 : 2))->get();
44770b57cec5SDimitry Andric   EVT PtrVT =
44780b57cec5SDimitry Andric       CurDAG->getTargetLoweringInfo().getPointerTy(CurDAG->getDataLayout());
44790b57cec5SDimitry Andric   bool isPPC64 = (PtrVT == MVT::i64);
4480e8d8bef9SDimitry Andric   SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
44810b57cec5SDimitry Andric 
4482e8d8bef9SDimitry Andric   SDValue LHS = N->getOperand(IsStrict ? 1 : 0);
4483e8d8bef9SDimitry Andric   SDValue RHS = N->getOperand(IsStrict ? 2 : 1);
4484e8d8bef9SDimitry Andric 
4485e8d8bef9SDimitry Andric   if (!IsStrict && !Subtarget->useCRBits() && isInt32Immediate(RHS, Imm)) {
44860b57cec5SDimitry Andric     // We can codegen setcc op, imm very efficiently compared to a brcond.
44870b57cec5SDimitry Andric     // Check for those cases here.
44880b57cec5SDimitry Andric     // setcc op, 0
44890b57cec5SDimitry Andric     if (Imm == 0) {
4490e8d8bef9SDimitry Andric       SDValue Op = LHS;
44910b57cec5SDimitry Andric       switch (CC) {
44920b57cec5SDimitry Andric       default: break;
44930b57cec5SDimitry Andric       case ISD::SETEQ: {
44940b57cec5SDimitry Andric         Op = SDValue(CurDAG->getMachineNode(PPC::CNTLZW, dl, MVT::i32, Op), 0);
44950b57cec5SDimitry Andric         SDValue Ops[] = { Op, getI32Imm(27, dl), getI32Imm(5, dl),
44960b57cec5SDimitry Andric                           getI32Imm(31, dl) };
44970b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
44980b57cec5SDimitry Andric         return true;
44990b57cec5SDimitry Andric       }
45000b57cec5SDimitry Andric       case ISD::SETNE: {
45010b57cec5SDimitry Andric         if (isPPC64) break;
45020b57cec5SDimitry Andric         SDValue AD =
45030b57cec5SDimitry Andric           SDValue(CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue,
45040b57cec5SDimitry Andric                                          Op, getI32Imm(~0U, dl)), 0);
45050b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1));
45060b57cec5SDimitry Andric         return true;
45070b57cec5SDimitry Andric       }
45080b57cec5SDimitry Andric       case ISD::SETLT: {
45090b57cec5SDimitry Andric         SDValue Ops[] = { Op, getI32Imm(1, dl), getI32Imm(31, dl),
45100b57cec5SDimitry Andric                           getI32Imm(31, dl) };
45110b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
45120b57cec5SDimitry Andric         return true;
45130b57cec5SDimitry Andric       }
45140b57cec5SDimitry Andric       case ISD::SETGT: {
45150b57cec5SDimitry Andric         SDValue T =
45160b57cec5SDimitry Andric           SDValue(CurDAG->getMachineNode(PPC::NEG, dl, MVT::i32, Op), 0);
45170b57cec5SDimitry Andric         T = SDValue(CurDAG->getMachineNode(PPC::ANDC, dl, MVT::i32, T, Op), 0);
45180b57cec5SDimitry Andric         SDValue Ops[] = { T, getI32Imm(1, dl), getI32Imm(31, dl),
45190b57cec5SDimitry Andric                           getI32Imm(31, dl) };
45200b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
45210b57cec5SDimitry Andric         return true;
45220b57cec5SDimitry Andric       }
45230b57cec5SDimitry Andric       }
45240b57cec5SDimitry Andric     } else if (Imm == ~0U) {        // setcc op, -1
4525e8d8bef9SDimitry Andric       SDValue Op = LHS;
45260b57cec5SDimitry Andric       switch (CC) {
45270b57cec5SDimitry Andric       default: break;
45280b57cec5SDimitry Andric       case ISD::SETEQ:
45290b57cec5SDimitry Andric         if (isPPC64) break;
45300b57cec5SDimitry Andric         Op = SDValue(CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue,
45310b57cec5SDimitry Andric                                             Op, getI32Imm(1, dl)), 0);
45320b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32,
45330b57cec5SDimitry Andric                              SDValue(CurDAG->getMachineNode(PPC::LI, dl,
45340b57cec5SDimitry Andric                                                             MVT::i32,
45350b57cec5SDimitry Andric                                                             getI32Imm(0, dl)),
45360b57cec5SDimitry Andric                                      0), Op.getValue(1));
45370b57cec5SDimitry Andric         return true;
45380b57cec5SDimitry Andric       case ISD::SETNE: {
45390b57cec5SDimitry Andric         if (isPPC64) break;
45400b57cec5SDimitry Andric         Op = SDValue(CurDAG->getMachineNode(PPC::NOR, dl, MVT::i32, Op, Op), 0);
45410b57cec5SDimitry Andric         SDNode *AD = CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue,
45420b57cec5SDimitry Andric                                             Op, getI32Imm(~0U, dl));
45430b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, SDValue(AD, 0), Op,
45440b57cec5SDimitry Andric                              SDValue(AD, 1));
45450b57cec5SDimitry Andric         return true;
45460b57cec5SDimitry Andric       }
45470b57cec5SDimitry Andric       case ISD::SETLT: {
45480b57cec5SDimitry Andric         SDValue AD = SDValue(CurDAG->getMachineNode(PPC::ADDI, dl, MVT::i32, Op,
45490b57cec5SDimitry Andric                                                     getI32Imm(1, dl)), 0);
45500b57cec5SDimitry Andric         SDValue AN = SDValue(CurDAG->getMachineNode(PPC::AND, dl, MVT::i32, AD,
45510b57cec5SDimitry Andric                                                     Op), 0);
45520b57cec5SDimitry Andric         SDValue Ops[] = { AN, getI32Imm(1, dl), getI32Imm(31, dl),
45530b57cec5SDimitry Andric                           getI32Imm(31, dl) };
45540b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
45550b57cec5SDimitry Andric         return true;
45560b57cec5SDimitry Andric       }
45570b57cec5SDimitry Andric       case ISD::SETGT: {
45580b57cec5SDimitry Andric         SDValue Ops[] = { Op, getI32Imm(1, dl), getI32Imm(31, dl),
45590b57cec5SDimitry Andric                           getI32Imm(31, dl) };
45600b57cec5SDimitry Andric         Op = SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops), 0);
45610b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, getI32Imm(1, dl));
45620b57cec5SDimitry Andric         return true;
45630b57cec5SDimitry Andric       }
45640b57cec5SDimitry Andric       }
45650b57cec5SDimitry Andric     }
45660b57cec5SDimitry Andric   }
45670b57cec5SDimitry Andric 
45680b57cec5SDimitry Andric   // Altivec Vector compare instructions do not set any CR register by default and
45690b57cec5SDimitry Andric   // vector compare operations return the same type as the operands.
4570e8d8bef9SDimitry Andric   if (!IsStrict && LHS.getValueType().isVector()) {
4571e8d8bef9SDimitry Andric     if (Subtarget->hasSPE())
45720b57cec5SDimitry Andric       return false;
45730b57cec5SDimitry Andric 
45740b57cec5SDimitry Andric     EVT VecVT = LHS.getValueType();
45750b57cec5SDimitry Andric     bool Swap, Negate;
45765ffd83dbSDimitry Andric     unsigned int VCmpInst =
45775ffd83dbSDimitry Andric         getVCmpInst(VecVT.getSimpleVT(), CC, Subtarget->hasVSX(), Swap, Negate);
45780b57cec5SDimitry Andric     if (Swap)
45790b57cec5SDimitry Andric       std::swap(LHS, RHS);
45800b57cec5SDimitry Andric 
45810b57cec5SDimitry Andric     EVT ResVT = VecVT.changeVectorElementTypeToInteger();
45820b57cec5SDimitry Andric     if (Negate) {
45830b57cec5SDimitry Andric       SDValue VCmp(CurDAG->getMachineNode(VCmpInst, dl, ResVT, LHS, RHS), 0);
45845ffd83dbSDimitry Andric       CurDAG->SelectNodeTo(N, Subtarget->hasVSX() ? PPC::XXLNOR : PPC::VNOR,
45850b57cec5SDimitry Andric                            ResVT, VCmp, VCmp);
45860b57cec5SDimitry Andric       return true;
45870b57cec5SDimitry Andric     }
45880b57cec5SDimitry Andric 
45890b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, VCmpInst, ResVT, LHS, RHS);
45900b57cec5SDimitry Andric     return true;
45910b57cec5SDimitry Andric   }
45920b57cec5SDimitry Andric 
45935ffd83dbSDimitry Andric   if (Subtarget->useCRBits())
45940b57cec5SDimitry Andric     return false;
45950b57cec5SDimitry Andric 
45960b57cec5SDimitry Andric   bool Inv;
45970b57cec5SDimitry Andric   unsigned Idx = getCRIdxForSetCC(CC, Inv);
4598e8d8bef9SDimitry Andric   SDValue CCReg = SelectCC(LHS, RHS, CC, dl, Chain);
4599e8d8bef9SDimitry Andric   if (IsStrict)
4600e8d8bef9SDimitry Andric     CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 1), CCReg.getValue(1));
46010b57cec5SDimitry Andric   SDValue IntCR;
46020b57cec5SDimitry Andric 
46030b57cec5SDimitry Andric   // SPE e*cmp* instructions only set the 'gt' bit, so hard-code that
46040b57cec5SDimitry Andric   // The correct compare instruction is already set by SelectCC()
46055ffd83dbSDimitry Andric   if (Subtarget->hasSPE() && LHS.getValueType().isFloatingPoint()) {
46060b57cec5SDimitry Andric     Idx = 1;
46070b57cec5SDimitry Andric   }
46080b57cec5SDimitry Andric 
46090b57cec5SDimitry Andric   // Force the ccreg into CR7.
46100b57cec5SDimitry Andric   SDValue CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32);
46110b57cec5SDimitry Andric 
461206c3fb27SDimitry Andric   SDValue InGlue;  // Null incoming flag value.
46130b57cec5SDimitry Andric   CCReg = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, CR7Reg, CCReg,
461406c3fb27SDimitry Andric                                InGlue).getValue(1);
46150b57cec5SDimitry Andric 
46160b57cec5SDimitry Andric   IntCR = SDValue(CurDAG->getMachineNode(PPC::MFOCRF, dl, MVT::i32, CR7Reg,
46170b57cec5SDimitry Andric                                          CCReg), 0);
46180b57cec5SDimitry Andric 
46190b57cec5SDimitry Andric   SDValue Ops[] = { IntCR, getI32Imm((32 - (3 - Idx)) & 31, dl),
46200b57cec5SDimitry Andric                       getI32Imm(31, dl), getI32Imm(31, dl) };
46210b57cec5SDimitry Andric   if (!Inv) {
46220b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
46230b57cec5SDimitry Andric     return true;
46240b57cec5SDimitry Andric   }
46250b57cec5SDimitry Andric 
46260b57cec5SDimitry Andric   // Get the specified bit.
46270b57cec5SDimitry Andric   SDValue Tmp =
46280b57cec5SDimitry Andric     SDValue(CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops), 0);
46290b57cec5SDimitry Andric   CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1, dl));
46300b57cec5SDimitry Andric   return true;
46310b57cec5SDimitry Andric }
46320b57cec5SDimitry Andric 
46330b57cec5SDimitry Andric /// Does this node represent a load/store node whose address can be represented
46340b57cec5SDimitry Andric /// with a register plus an immediate that's a multiple of \p Val:
isOffsetMultipleOf(SDNode * N,unsigned Val) const46350b57cec5SDimitry Andric bool PPCDAGToDAGISel::isOffsetMultipleOf(SDNode *N, unsigned Val) const {
46360b57cec5SDimitry Andric   LoadSDNode *LDN = dyn_cast<LoadSDNode>(N);
46370b57cec5SDimitry Andric   StoreSDNode *STN = dyn_cast<StoreSDNode>(N);
46380eae32dcSDimitry Andric   MemIntrinsicSDNode *MIN = dyn_cast<MemIntrinsicSDNode>(N);
46390b57cec5SDimitry Andric   SDValue AddrOp;
46400eae32dcSDimitry Andric   if (LDN || (MIN && MIN->getOpcode() == PPCISD::LD_SPLAT))
46410eae32dcSDimitry Andric     AddrOp = N->getOperand(1);
46420b57cec5SDimitry Andric   else if (STN)
46430b57cec5SDimitry Andric     AddrOp = STN->getOperand(2);
46440b57cec5SDimitry Andric 
46450b57cec5SDimitry Andric   // If the address points a frame object or a frame object with an offset,
46460b57cec5SDimitry Andric   // we need to check the object alignment.
46470b57cec5SDimitry Andric   short Imm = 0;
46480b57cec5SDimitry Andric   if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(
46490b57cec5SDimitry Andric           AddrOp.getOpcode() == ISD::ADD ? AddrOp.getOperand(0) :
46500b57cec5SDimitry Andric                                            AddrOp)) {
46510b57cec5SDimitry Andric     // If op0 is a frame index that is under aligned, we can't do it either,
46520b57cec5SDimitry Andric     // because it is translated to r31 or r1 + slot + offset. We won't know the
46530b57cec5SDimitry Andric     // slot number until the stack frame is finalized.
46540b57cec5SDimitry Andric     const MachineFrameInfo &MFI = CurDAG->getMachineFunction().getFrameInfo();
46555ffd83dbSDimitry Andric     unsigned SlotAlign = MFI.getObjectAlign(FI->getIndex()).value();
46560b57cec5SDimitry Andric     if ((SlotAlign % Val) != 0)
46570b57cec5SDimitry Andric       return false;
46580b57cec5SDimitry Andric 
46590b57cec5SDimitry Andric     // If we have an offset, we need further check on the offset.
46600b57cec5SDimitry Andric     if (AddrOp.getOpcode() != ISD::ADD)
46610b57cec5SDimitry Andric       return true;
46620b57cec5SDimitry Andric   }
46630b57cec5SDimitry Andric 
46640b57cec5SDimitry Andric   if (AddrOp.getOpcode() == ISD::ADD)
46650b57cec5SDimitry Andric     return isIntS16Immediate(AddrOp.getOperand(1), Imm) && !(Imm % Val);
46660b57cec5SDimitry Andric 
46670b57cec5SDimitry Andric   // If the address comes from the outside, the offset will be zero.
46680b57cec5SDimitry Andric   return AddrOp.getOpcode() == ISD::CopyFromReg;
46690b57cec5SDimitry Andric }
46700b57cec5SDimitry Andric 
transferMemOperands(SDNode * N,SDNode * Result)46710b57cec5SDimitry Andric void PPCDAGToDAGISel::transferMemOperands(SDNode *N, SDNode *Result) {
46720b57cec5SDimitry Andric   // Transfer memoperands.
46730b57cec5SDimitry Andric   MachineMemOperand *MemOp = cast<MemSDNode>(N)->getMemOperand();
46740b57cec5SDimitry Andric   CurDAG->setNodeMemRefs(cast<MachineSDNode>(Result), {MemOp});
46750b57cec5SDimitry Andric }
46760b57cec5SDimitry Andric 
mayUseP9Setb(SDNode * N,const ISD::CondCode & CC,SelectionDAG * DAG,bool & NeedSwapOps,bool & IsUnCmp)46770b57cec5SDimitry Andric static bool mayUseP9Setb(SDNode *N, const ISD::CondCode &CC, SelectionDAG *DAG,
46780b57cec5SDimitry Andric                          bool &NeedSwapOps, bool &IsUnCmp) {
46790b57cec5SDimitry Andric 
46800b57cec5SDimitry Andric   assert(N->getOpcode() == ISD::SELECT_CC && "Expecting a SELECT_CC here.");
46810b57cec5SDimitry Andric 
46820b57cec5SDimitry Andric   SDValue LHS = N->getOperand(0);
46830b57cec5SDimitry Andric   SDValue RHS = N->getOperand(1);
46840b57cec5SDimitry Andric   SDValue TrueRes = N->getOperand(2);
46850b57cec5SDimitry Andric   SDValue FalseRes = N->getOperand(3);
46860b57cec5SDimitry Andric   ConstantSDNode *TrueConst = dyn_cast<ConstantSDNode>(TrueRes);
46875ffd83dbSDimitry Andric   if (!TrueConst || (N->getSimpleValueType(0) != MVT::i64 &&
46885ffd83dbSDimitry Andric                      N->getSimpleValueType(0) != MVT::i32))
46890b57cec5SDimitry Andric     return false;
46900b57cec5SDimitry Andric 
46910b57cec5SDimitry Andric   // We are looking for any of:
46920b57cec5SDimitry Andric   // (select_cc lhs, rhs,  1, (sext (setcc [lr]hs, [lr]hs, cc2)), cc1)
46930b57cec5SDimitry Andric   // (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, cc2)), cc1)
46940b57cec5SDimitry Andric   // (select_cc lhs, rhs,  0, (select_cc [lr]hs, [lr]hs,  1, -1, cc2), seteq)
46950b57cec5SDimitry Andric   // (select_cc lhs, rhs,  0, (select_cc [lr]hs, [lr]hs, -1,  1, cc2), seteq)
46960b57cec5SDimitry Andric   int64_t TrueResVal = TrueConst->getSExtValue();
46970b57cec5SDimitry Andric   if ((TrueResVal < -1 || TrueResVal > 1) ||
46980b57cec5SDimitry Andric       (TrueResVal == -1 && FalseRes.getOpcode() != ISD::ZERO_EXTEND) ||
46990b57cec5SDimitry Andric       (TrueResVal == 1 && FalseRes.getOpcode() != ISD::SIGN_EXTEND) ||
47000b57cec5SDimitry Andric       (TrueResVal == 0 &&
47010b57cec5SDimitry Andric        (FalseRes.getOpcode() != ISD::SELECT_CC || CC != ISD::SETEQ)))
47020b57cec5SDimitry Andric     return false;
47030b57cec5SDimitry Andric 
4704e8d8bef9SDimitry Andric   SDValue SetOrSelCC = FalseRes.getOpcode() == ISD::SELECT_CC
4705e8d8bef9SDimitry Andric                            ? FalseRes
4706e8d8bef9SDimitry Andric                            : FalseRes.getOperand(0);
4707e8d8bef9SDimitry Andric   bool InnerIsSel = SetOrSelCC.getOpcode() == ISD::SELECT_CC;
47080b57cec5SDimitry Andric   if (SetOrSelCC.getOpcode() != ISD::SETCC &&
47090b57cec5SDimitry Andric       SetOrSelCC.getOpcode() != ISD::SELECT_CC)
47100b57cec5SDimitry Andric     return false;
47110b57cec5SDimitry Andric 
47120b57cec5SDimitry Andric   // Without this setb optimization, the outer SELECT_CC will be manually
47130b57cec5SDimitry Andric   // selected to SELECT_CC_I4/SELECT_CC_I8 Pseudo, then expand-isel-pseudos pass
47140b57cec5SDimitry Andric   // transforms pseudo instruction to isel instruction. When there are more than
47150b57cec5SDimitry Andric   // one use for result like zext/sext, with current optimization we only see
47160b57cec5SDimitry Andric   // isel is replaced by setb but can't see any significant gain. Since
47170b57cec5SDimitry Andric   // setb has longer latency than original isel, we should avoid this. Another
47180b57cec5SDimitry Andric   // point is that setb requires comparison always kept, it can break the
47190b57cec5SDimitry Andric   // opportunity to get the comparison away if we have in future.
47200b57cec5SDimitry Andric   if (!SetOrSelCC.hasOneUse() || (!InnerIsSel && !FalseRes.hasOneUse()))
47210b57cec5SDimitry Andric     return false;
47220b57cec5SDimitry Andric 
47230b57cec5SDimitry Andric   SDValue InnerLHS = SetOrSelCC.getOperand(0);
47240b57cec5SDimitry Andric   SDValue InnerRHS = SetOrSelCC.getOperand(1);
47250b57cec5SDimitry Andric   ISD::CondCode InnerCC =
47260b57cec5SDimitry Andric       cast<CondCodeSDNode>(SetOrSelCC.getOperand(InnerIsSel ? 4 : 2))->get();
47270b57cec5SDimitry Andric   // If the inner comparison is a select_cc, make sure the true/false values are
47280b57cec5SDimitry Andric   // 1/-1 and canonicalize it if needed.
47290b57cec5SDimitry Andric   if (InnerIsSel) {
47300b57cec5SDimitry Andric     ConstantSDNode *SelCCTrueConst =
47310b57cec5SDimitry Andric         dyn_cast<ConstantSDNode>(SetOrSelCC.getOperand(2));
47320b57cec5SDimitry Andric     ConstantSDNode *SelCCFalseConst =
47330b57cec5SDimitry Andric         dyn_cast<ConstantSDNode>(SetOrSelCC.getOperand(3));
47340b57cec5SDimitry Andric     if (!SelCCTrueConst || !SelCCFalseConst)
47350b57cec5SDimitry Andric       return false;
47360b57cec5SDimitry Andric     int64_t SelCCTVal = SelCCTrueConst->getSExtValue();
47370b57cec5SDimitry Andric     int64_t SelCCFVal = SelCCFalseConst->getSExtValue();
47380b57cec5SDimitry Andric     // The values must be -1/1 (requiring a swap) or 1/-1.
47390b57cec5SDimitry Andric     if (SelCCTVal == -1 && SelCCFVal == 1) {
47400b57cec5SDimitry Andric       std::swap(InnerLHS, InnerRHS);
47410b57cec5SDimitry Andric     } else if (SelCCTVal != 1 || SelCCFVal != -1)
47420b57cec5SDimitry Andric       return false;
47430b57cec5SDimitry Andric   }
47440b57cec5SDimitry Andric 
47450b57cec5SDimitry Andric   // Canonicalize unsigned case
47460b57cec5SDimitry Andric   if (InnerCC == ISD::SETULT || InnerCC == ISD::SETUGT) {
47470b57cec5SDimitry Andric     IsUnCmp = true;
47480b57cec5SDimitry Andric     InnerCC = (InnerCC == ISD::SETULT) ? ISD::SETLT : ISD::SETGT;
47490b57cec5SDimitry Andric   }
47500b57cec5SDimitry Andric 
47510b57cec5SDimitry Andric   bool InnerSwapped = false;
47520b57cec5SDimitry Andric   if (LHS == InnerRHS && RHS == InnerLHS)
47530b57cec5SDimitry Andric     InnerSwapped = true;
47540b57cec5SDimitry Andric   else if (LHS != InnerLHS || RHS != InnerRHS)
47550b57cec5SDimitry Andric     return false;
47560b57cec5SDimitry Andric 
47570b57cec5SDimitry Andric   switch (CC) {
47580b57cec5SDimitry Andric   // (select_cc lhs, rhs,  0, \
47590b57cec5SDimitry Andric   //     (select_cc [lr]hs, [lr]hs, 1, -1, setlt/setgt), seteq)
47600b57cec5SDimitry Andric   case ISD::SETEQ:
47610b57cec5SDimitry Andric     if (!InnerIsSel)
47620b57cec5SDimitry Andric       return false;
47630b57cec5SDimitry Andric     if (InnerCC != ISD::SETLT && InnerCC != ISD::SETGT)
47640b57cec5SDimitry Andric       return false;
47650b57cec5SDimitry Andric     NeedSwapOps = (InnerCC == ISD::SETGT) ? InnerSwapped : !InnerSwapped;
47660b57cec5SDimitry Andric     break;
47670b57cec5SDimitry Andric 
47680b57cec5SDimitry Andric   // (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, setne)), setu?lt)
47690b57cec5SDimitry Andric   // (select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setgt)), setu?lt)
47700b57cec5SDimitry Andric   // (select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setlt)), setu?lt)
47710b57cec5SDimitry Andric   // (select_cc lhs, rhs, 1, (sext (setcc [lr]hs, [lr]hs, setne)), setu?lt)
47720b57cec5SDimitry Andric   // (select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setgt)), setu?lt)
47730b57cec5SDimitry Andric   // (select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setlt)), setu?lt)
47740b57cec5SDimitry Andric   case ISD::SETULT:
47750b57cec5SDimitry Andric     if (!IsUnCmp && InnerCC != ISD::SETNE)
47760b57cec5SDimitry Andric       return false;
47770b57cec5SDimitry Andric     IsUnCmp = true;
4778bdd1243dSDimitry Andric     [[fallthrough]];
47790b57cec5SDimitry Andric   case ISD::SETLT:
47800b57cec5SDimitry Andric     if (InnerCC == ISD::SETNE || (InnerCC == ISD::SETGT && !InnerSwapped) ||
47810b57cec5SDimitry Andric         (InnerCC == ISD::SETLT && InnerSwapped))
47820b57cec5SDimitry Andric       NeedSwapOps = (TrueResVal == 1);
47830b57cec5SDimitry Andric     else
47840b57cec5SDimitry Andric       return false;
47850b57cec5SDimitry Andric     break;
47860b57cec5SDimitry Andric 
47870b57cec5SDimitry Andric   // (select_cc lhs, rhs, 1, (sext (setcc [lr]hs, [lr]hs, setne)), setu?gt)
47880b57cec5SDimitry Andric   // (select_cc lhs, rhs, 1, (sext (setcc lhs, rhs, setlt)), setu?gt)
47890b57cec5SDimitry Andric   // (select_cc lhs, rhs, 1, (sext (setcc rhs, lhs, setgt)), setu?gt)
47900b57cec5SDimitry Andric   // (select_cc lhs, rhs, -1, (zext (setcc [lr]hs, [lr]hs, setne)), setu?gt)
47910b57cec5SDimitry Andric   // (select_cc lhs, rhs, -1, (zext (setcc lhs, rhs, setlt)), setu?gt)
47920b57cec5SDimitry Andric   // (select_cc lhs, rhs, -1, (zext (setcc rhs, lhs, setgt)), setu?gt)
47930b57cec5SDimitry Andric   case ISD::SETUGT:
47940b57cec5SDimitry Andric     if (!IsUnCmp && InnerCC != ISD::SETNE)
47950b57cec5SDimitry Andric       return false;
47960b57cec5SDimitry Andric     IsUnCmp = true;
4797bdd1243dSDimitry Andric     [[fallthrough]];
47980b57cec5SDimitry Andric   case ISD::SETGT:
47990b57cec5SDimitry Andric     if (InnerCC == ISD::SETNE || (InnerCC == ISD::SETLT && !InnerSwapped) ||
48000b57cec5SDimitry Andric         (InnerCC == ISD::SETGT && InnerSwapped))
48010b57cec5SDimitry Andric       NeedSwapOps = (TrueResVal == -1);
48020b57cec5SDimitry Andric     else
48030b57cec5SDimitry Andric       return false;
48040b57cec5SDimitry Andric     break;
48050b57cec5SDimitry Andric 
48060b57cec5SDimitry Andric   default:
48070b57cec5SDimitry Andric     return false;
48080b57cec5SDimitry Andric   }
48090b57cec5SDimitry Andric 
48100b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Found a node that can be lowered to a SETB: ");
48110b57cec5SDimitry Andric   LLVM_DEBUG(N->dump());
48120b57cec5SDimitry Andric 
48130b57cec5SDimitry Andric   return true;
48140b57cec5SDimitry Andric }
48150b57cec5SDimitry Andric 
4816e8d8bef9SDimitry Andric // Return true if it's a software square-root/divide operand.
isSWTestOp(SDValue N)4817e8d8bef9SDimitry Andric static bool isSWTestOp(SDValue N) {
4818e8d8bef9SDimitry Andric   if (N.getOpcode() == PPCISD::FTSQRT)
4819e8d8bef9SDimitry Andric     return true;
482081ad6265SDimitry Andric   if (N.getNumOperands() < 1 || !isa<ConstantSDNode>(N.getOperand(0)) ||
482181ad6265SDimitry Andric       N.getOpcode() != ISD::INTRINSIC_WO_CHAIN)
4822e8d8bef9SDimitry Andric     return false;
4823e8d8bef9SDimitry Andric   switch (N.getConstantOperandVal(0)) {
4824e8d8bef9SDimitry Andric   case Intrinsic::ppc_vsx_xvtdivdp:
4825e8d8bef9SDimitry Andric   case Intrinsic::ppc_vsx_xvtdivsp:
4826e8d8bef9SDimitry Andric   case Intrinsic::ppc_vsx_xvtsqrtdp:
4827e8d8bef9SDimitry Andric   case Intrinsic::ppc_vsx_xvtsqrtsp:
4828e8d8bef9SDimitry Andric     return true;
4829e8d8bef9SDimitry Andric   }
4830e8d8bef9SDimitry Andric   return false;
4831e8d8bef9SDimitry Andric }
4832e8d8bef9SDimitry Andric 
tryFoldSWTestBRCC(SDNode * N)4833e8d8bef9SDimitry Andric bool PPCDAGToDAGISel::tryFoldSWTestBRCC(SDNode *N) {
4834e8d8bef9SDimitry Andric   assert(N->getOpcode() == ISD::BR_CC && "ISD::BR_CC is expected.");
4835e8d8bef9SDimitry Andric   // We are looking for following patterns, where `truncate to i1` actually has
4836e8d8bef9SDimitry Andric   // the same semantic with `and 1`.
4837e8d8bef9SDimitry Andric   // (br_cc seteq, (truncateToi1 SWTestOp), 0) -> (BCC PRED_NU, SWTestOp)
4838e8d8bef9SDimitry Andric   // (br_cc seteq, (and SWTestOp, 2), 0) -> (BCC PRED_NE, SWTestOp)
4839e8d8bef9SDimitry Andric   // (br_cc seteq, (and SWTestOp, 4), 0) -> (BCC PRED_LE, SWTestOp)
4840e8d8bef9SDimitry Andric   // (br_cc seteq, (and SWTestOp, 8), 0) -> (BCC PRED_GE, SWTestOp)
4841e8d8bef9SDimitry Andric   // (br_cc setne, (truncateToi1 SWTestOp), 0) -> (BCC PRED_UN, SWTestOp)
4842e8d8bef9SDimitry Andric   // (br_cc setne, (and SWTestOp, 2), 0) -> (BCC PRED_EQ, SWTestOp)
4843e8d8bef9SDimitry Andric   // (br_cc setne, (and SWTestOp, 4), 0) -> (BCC PRED_GT, SWTestOp)
4844e8d8bef9SDimitry Andric   // (br_cc setne, (and SWTestOp, 8), 0) -> (BCC PRED_LT, SWTestOp)
4845e8d8bef9SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
4846e8d8bef9SDimitry Andric   if (CC != ISD::SETEQ && CC != ISD::SETNE)
4847e8d8bef9SDimitry Andric     return false;
4848e8d8bef9SDimitry Andric 
4849e8d8bef9SDimitry Andric   SDValue CmpRHS = N->getOperand(3);
48505f757f3fSDimitry Andric   if (!isNullConstant(CmpRHS))
4851e8d8bef9SDimitry Andric     return false;
4852e8d8bef9SDimitry Andric 
4853e8d8bef9SDimitry Andric   SDValue CmpLHS = N->getOperand(2);
4854e8d8bef9SDimitry Andric   if (CmpLHS.getNumOperands() < 1 || !isSWTestOp(CmpLHS.getOperand(0)))
4855e8d8bef9SDimitry Andric     return false;
4856e8d8bef9SDimitry Andric 
4857e8d8bef9SDimitry Andric   unsigned PCC = 0;
4858e8d8bef9SDimitry Andric   bool IsCCNE = CC == ISD::SETNE;
4859e8d8bef9SDimitry Andric   if (CmpLHS.getOpcode() == ISD::AND &&
4860e8d8bef9SDimitry Andric       isa<ConstantSDNode>(CmpLHS.getOperand(1)))
4861e8d8bef9SDimitry Andric     switch (CmpLHS.getConstantOperandVal(1)) {
4862e8d8bef9SDimitry Andric     case 1:
4863e8d8bef9SDimitry Andric       PCC = IsCCNE ? PPC::PRED_UN : PPC::PRED_NU;
4864e8d8bef9SDimitry Andric       break;
4865e8d8bef9SDimitry Andric     case 2:
4866e8d8bef9SDimitry Andric       PCC = IsCCNE ? PPC::PRED_EQ : PPC::PRED_NE;
4867e8d8bef9SDimitry Andric       break;
4868e8d8bef9SDimitry Andric     case 4:
4869e8d8bef9SDimitry Andric       PCC = IsCCNE ? PPC::PRED_GT : PPC::PRED_LE;
4870e8d8bef9SDimitry Andric       break;
4871e8d8bef9SDimitry Andric     case 8:
4872e8d8bef9SDimitry Andric       PCC = IsCCNE ? PPC::PRED_LT : PPC::PRED_GE;
4873e8d8bef9SDimitry Andric       break;
4874e8d8bef9SDimitry Andric     default:
4875e8d8bef9SDimitry Andric       return false;
4876e8d8bef9SDimitry Andric     }
4877e8d8bef9SDimitry Andric   else if (CmpLHS.getOpcode() == ISD::TRUNCATE &&
4878e8d8bef9SDimitry Andric            CmpLHS.getValueType() == MVT::i1)
4879e8d8bef9SDimitry Andric     PCC = IsCCNE ? PPC::PRED_UN : PPC::PRED_NU;
4880e8d8bef9SDimitry Andric 
4881e8d8bef9SDimitry Andric   if (PCC) {
4882e8d8bef9SDimitry Andric     SDLoc dl(N);
4883e8d8bef9SDimitry Andric     SDValue Ops[] = {getI32Imm(PCC, dl), CmpLHS.getOperand(0), N->getOperand(4),
4884e8d8bef9SDimitry Andric                      N->getOperand(0)};
4885e8d8bef9SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops);
4886e8d8bef9SDimitry Andric     return true;
4887e8d8bef9SDimitry Andric   }
4888e8d8bef9SDimitry Andric   return false;
4889e8d8bef9SDimitry Andric }
4890e8d8bef9SDimitry Andric 
trySelectLoopCountIntrinsic(SDNode * N)4891bdd1243dSDimitry Andric bool PPCDAGToDAGISel::trySelectLoopCountIntrinsic(SDNode *N) {
4892bdd1243dSDimitry Andric   // Sometimes the promoted value of the intrinsic is ANDed by some non-zero
4893bdd1243dSDimitry Andric   // value, for example when crbits is disabled. If so, select the
4894bdd1243dSDimitry Andric   // loop_decrement intrinsics now.
4895bdd1243dSDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
4896bdd1243dSDimitry Andric   SDValue LHS = N->getOperand(2), RHS = N->getOperand(3);
4897bdd1243dSDimitry Andric 
4898bdd1243dSDimitry Andric   if (LHS.getOpcode() != ISD::AND || !isa<ConstantSDNode>(LHS.getOperand(1)) ||
4899bdd1243dSDimitry Andric       isNullConstant(LHS.getOperand(1)))
4900bdd1243dSDimitry Andric     return false;
4901bdd1243dSDimitry Andric 
4902bdd1243dSDimitry Andric   if (LHS.getOperand(0).getOpcode() != ISD::INTRINSIC_W_CHAIN ||
4903647cbc5dSDimitry Andric       LHS.getOperand(0).getConstantOperandVal(1) != Intrinsic::loop_decrement)
4904bdd1243dSDimitry Andric     return false;
4905bdd1243dSDimitry Andric 
4906bdd1243dSDimitry Andric   if (!isa<ConstantSDNode>(RHS))
4907bdd1243dSDimitry Andric     return false;
4908bdd1243dSDimitry Andric 
4909bdd1243dSDimitry Andric   assert((CC == ISD::SETEQ || CC == ISD::SETNE) &&
4910bdd1243dSDimitry Andric          "Counter decrement comparison is not EQ or NE");
4911bdd1243dSDimitry Andric 
4912bdd1243dSDimitry Andric   SDValue OldDecrement = LHS.getOperand(0);
4913bdd1243dSDimitry Andric   assert(OldDecrement.hasOneUse() && "loop decrement has more than one use!");
4914bdd1243dSDimitry Andric 
4915bdd1243dSDimitry Andric   SDLoc DecrementLoc(OldDecrement);
4916bdd1243dSDimitry Andric   SDValue ChainInput = OldDecrement.getOperand(0);
4917bdd1243dSDimitry Andric   SDValue DecrementOps[] = {Subtarget->isPPC64() ? getI64Imm(1, DecrementLoc)
4918bdd1243dSDimitry Andric                                                  : getI32Imm(1, DecrementLoc)};
4919bdd1243dSDimitry Andric   unsigned DecrementOpcode =
4920bdd1243dSDimitry Andric       Subtarget->isPPC64() ? PPC::DecreaseCTR8loop : PPC::DecreaseCTRloop;
4921bdd1243dSDimitry Andric   SDNode *NewDecrement = CurDAG->getMachineNode(DecrementOpcode, DecrementLoc,
4922bdd1243dSDimitry Andric                                                 MVT::i1, DecrementOps);
4923bdd1243dSDimitry Andric 
49241db9f3b2SDimitry Andric   unsigned Val = RHS->getAsZExtVal();
4925bdd1243dSDimitry Andric   bool IsBranchOnTrue = (CC == ISD::SETEQ && Val) || (CC == ISD::SETNE && !Val);
4926bdd1243dSDimitry Andric   unsigned Opcode = IsBranchOnTrue ? PPC::BC : PPC::BCn;
4927bdd1243dSDimitry Andric 
4928bdd1243dSDimitry Andric   ReplaceUses(LHS.getValue(0), LHS.getOperand(1));
4929bdd1243dSDimitry Andric   CurDAG->RemoveDeadNode(LHS.getNode());
4930bdd1243dSDimitry Andric 
4931bdd1243dSDimitry Andric   // Mark the old loop_decrement intrinsic as dead.
4932bdd1243dSDimitry Andric   ReplaceUses(OldDecrement.getValue(1), ChainInput);
4933bdd1243dSDimitry Andric   CurDAG->RemoveDeadNode(OldDecrement.getNode());
4934bdd1243dSDimitry Andric 
4935bdd1243dSDimitry Andric   SDValue Chain = CurDAG->getNode(ISD::TokenFactor, SDLoc(N), MVT::Other,
4936bdd1243dSDimitry Andric                                   ChainInput, N->getOperand(0));
4937bdd1243dSDimitry Andric 
4938bdd1243dSDimitry Andric   CurDAG->SelectNodeTo(N, Opcode, MVT::Other, SDValue(NewDecrement, 0),
4939bdd1243dSDimitry Andric                        N->getOperand(4), Chain);
4940bdd1243dSDimitry Andric   return true;
4941bdd1243dSDimitry Andric }
4942bdd1243dSDimitry Andric 
tryAsSingleRLWINM(SDNode * N)49435ffd83dbSDimitry Andric bool PPCDAGToDAGISel::tryAsSingleRLWINM(SDNode *N) {
49445ffd83dbSDimitry Andric   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
49455ffd83dbSDimitry Andric   unsigned Imm;
49465ffd83dbSDimitry Andric   if (!isInt32Immediate(N->getOperand(1), Imm))
4947480093f4SDimitry Andric     return false;
4948480093f4SDimitry Andric 
4949480093f4SDimitry Andric   SDLoc dl(N);
4950480093f4SDimitry Andric   SDValue Val = N->getOperand(0);
49515ffd83dbSDimitry Andric   unsigned SH, MB, ME;
4952480093f4SDimitry Andric   // If this is an and of a value rotated between 0 and 31 bits and then and'd
4953480093f4SDimitry Andric   // with a mask, emit rlwinm
49545ffd83dbSDimitry Andric   if (isRotateAndMask(Val.getNode(), Imm, false, SH, MB, ME)) {
49555ffd83dbSDimitry Andric     Val = Val.getOperand(0);
4956480093f4SDimitry Andric     SDValue Ops[] = {Val, getI32Imm(SH, dl), getI32Imm(MB, dl),
4957480093f4SDimitry Andric                      getI32Imm(ME, dl)};
4958480093f4SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
4959480093f4SDimitry Andric     return true;
4960480093f4SDimitry Andric   }
4961480093f4SDimitry Andric 
4962480093f4SDimitry Andric   // If this is just a masked value where the input is not handled, and
4963480093f4SDimitry Andric   // is not a rotate-left (handled by a pattern in the .td file), emit rlwinm
49645ffd83dbSDimitry Andric   if (isRunOfOnes(Imm, MB, ME) && Val.getOpcode() != ISD::ROTL) {
4965480093f4SDimitry Andric     SDValue Ops[] = {Val, getI32Imm(0, dl), getI32Imm(MB, dl),
4966480093f4SDimitry Andric                      getI32Imm(ME, dl)};
4967480093f4SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
4968480093f4SDimitry Andric     return true;
4969480093f4SDimitry Andric   }
49705ffd83dbSDimitry Andric 
4971480093f4SDimitry Andric   // AND X, 0 -> 0, not "rlwinm 32".
4972480093f4SDimitry Andric   if (Imm == 0) {
4973480093f4SDimitry Andric     ReplaceUses(SDValue(N, 0), N->getOperand(1));
4974480093f4SDimitry Andric     return true;
4975480093f4SDimitry Andric   }
4976480093f4SDimitry Andric 
49775ffd83dbSDimitry Andric   return false;
49785ffd83dbSDimitry Andric }
49795ffd83dbSDimitry Andric 
tryAsSingleRLWINM8(SDNode * N)49805ffd83dbSDimitry Andric bool PPCDAGToDAGISel::tryAsSingleRLWINM8(SDNode *N) {
49815ffd83dbSDimitry Andric   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
49825ffd83dbSDimitry Andric   uint64_t Imm64;
49835ffd83dbSDimitry Andric   if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64))
49845ffd83dbSDimitry Andric     return false;
49855ffd83dbSDimitry Andric 
49865ffd83dbSDimitry Andric   unsigned MB, ME;
49875ffd83dbSDimitry Andric   if (isRunOfOnes64(Imm64, MB, ME) && MB >= 32 && MB <= ME) {
49885ffd83dbSDimitry Andric     //                MB  ME
49895ffd83dbSDimitry Andric     // +----------------------+
49905ffd83dbSDimitry Andric     // |xxxxxxxxxxx00011111000|
49915ffd83dbSDimitry Andric     // +----------------------+
49925ffd83dbSDimitry Andric     //  0         32         64
49935ffd83dbSDimitry Andric     // We can only do it if the MB is larger than 32 and MB <= ME
49945ffd83dbSDimitry Andric     // as RLWINM will replace the contents of [0 - 32) with [32 - 64) even
49955ffd83dbSDimitry Andric     // we didn't rotate it.
49965ffd83dbSDimitry Andric     SDLoc dl(N);
49975ffd83dbSDimitry Andric     SDValue Ops[] = {N->getOperand(0), getI64Imm(0, dl), getI64Imm(MB - 32, dl),
49985ffd83dbSDimitry Andric                      getI64Imm(ME - 32, dl)};
49995ffd83dbSDimitry Andric     CurDAG->SelectNodeTo(N, PPC::RLWINM8, MVT::i64, Ops);
50005ffd83dbSDimitry Andric     return true;
50015ffd83dbSDimitry Andric   }
50025ffd83dbSDimitry Andric 
50035ffd83dbSDimitry Andric   return false;
50045ffd83dbSDimitry Andric }
50055ffd83dbSDimitry Andric 
tryAsPairOfRLDICL(SDNode * N)50065ffd83dbSDimitry Andric bool PPCDAGToDAGISel::tryAsPairOfRLDICL(SDNode *N) {
50075ffd83dbSDimitry Andric   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
50085ffd83dbSDimitry Andric   uint64_t Imm64;
50095ffd83dbSDimitry Andric   if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64))
50105ffd83dbSDimitry Andric     return false;
50115ffd83dbSDimitry Andric 
50125ffd83dbSDimitry Andric   // Do nothing if it is 16-bit imm as the pattern in the .td file handle
50135ffd83dbSDimitry Andric   // it well with "andi.".
50145ffd83dbSDimitry Andric   if (isUInt<16>(Imm64))
50155ffd83dbSDimitry Andric     return false;
50165ffd83dbSDimitry Andric 
50175ffd83dbSDimitry Andric   SDLoc Loc(N);
50185ffd83dbSDimitry Andric   SDValue Val = N->getOperand(0);
50195ffd83dbSDimitry Andric 
50205ffd83dbSDimitry Andric   // Optimized with two rldicl's as follows:
50215ffd83dbSDimitry Andric   // Add missing bits on left to the mask and check that the mask is a
50225ffd83dbSDimitry Andric   // wrapped run of ones, i.e.
50235ffd83dbSDimitry Andric   // Change pattern |0001111100000011111111|
50245ffd83dbSDimitry Andric   //             to |1111111100000011111111|.
502506c3fb27SDimitry Andric   unsigned NumOfLeadingZeros = llvm::countl_zero(Imm64);
50265ffd83dbSDimitry Andric   if (NumOfLeadingZeros != 0)
50275ffd83dbSDimitry Andric     Imm64 |= maskLeadingOnes<uint64_t>(NumOfLeadingZeros);
50285ffd83dbSDimitry Andric 
50295ffd83dbSDimitry Andric   unsigned MB, ME;
50305ffd83dbSDimitry Andric   if (!isRunOfOnes64(Imm64, MB, ME))
50315ffd83dbSDimitry Andric     return false;
50325ffd83dbSDimitry Andric 
50335ffd83dbSDimitry Andric   //         ME     MB                   MB-ME+63
50345ffd83dbSDimitry Andric   // +----------------------+     +----------------------+
50355ffd83dbSDimitry Andric   // |1111111100000011111111| ->  |0000001111111111111111|
50365ffd83dbSDimitry Andric   // +----------------------+     +----------------------+
50375ffd83dbSDimitry Andric   //  0                    63      0                    63
50385ffd83dbSDimitry Andric   // There are ME + 1 ones on the left and (MB - ME + 63) & 63 zeros in between.
50395ffd83dbSDimitry Andric   unsigned OnesOnLeft = ME + 1;
50405ffd83dbSDimitry Andric   unsigned ZerosInBetween = (MB - ME + 63) & 63;
50415ffd83dbSDimitry Andric   // Rotate left by OnesOnLeft (so leading ones are now trailing ones) and clear
50425ffd83dbSDimitry Andric   // on the left the bits that are already zeros in the mask.
50435ffd83dbSDimitry Andric   Val = SDValue(CurDAG->getMachineNode(PPC::RLDICL, Loc, MVT::i64, Val,
50445ffd83dbSDimitry Andric                                        getI64Imm(OnesOnLeft, Loc),
50455ffd83dbSDimitry Andric                                        getI64Imm(ZerosInBetween, Loc)),
50465ffd83dbSDimitry Andric                 0);
50475ffd83dbSDimitry Andric   //        MB-ME+63                      ME     MB
50485ffd83dbSDimitry Andric   // +----------------------+     +----------------------+
50495ffd83dbSDimitry Andric   // |0000001111111111111111| ->  |0001111100000011111111|
50505ffd83dbSDimitry Andric   // +----------------------+     +----------------------+
50515ffd83dbSDimitry Andric   //  0                    63      0                    63
50525ffd83dbSDimitry Andric   // Rotate back by 64 - OnesOnLeft to undo previous rotate. Then clear on the
50535ffd83dbSDimitry Andric   // left the number of ones we previously added.
50545ffd83dbSDimitry Andric   SDValue Ops[] = {Val, getI64Imm(64 - OnesOnLeft, Loc),
50555ffd83dbSDimitry Andric                    getI64Imm(NumOfLeadingZeros, Loc)};
50565ffd83dbSDimitry Andric   CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops);
50575ffd83dbSDimitry Andric   return true;
50585ffd83dbSDimitry Andric }
50595ffd83dbSDimitry Andric 
tryAsSingleRLWIMI(SDNode * N)50605ffd83dbSDimitry Andric bool PPCDAGToDAGISel::tryAsSingleRLWIMI(SDNode *N) {
50615ffd83dbSDimitry Andric   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
50625ffd83dbSDimitry Andric   unsigned Imm;
50635ffd83dbSDimitry Andric   if (!isInt32Immediate(N->getOperand(1), Imm))
50645ffd83dbSDimitry Andric     return false;
50655ffd83dbSDimitry Andric 
50665ffd83dbSDimitry Andric   SDValue Val = N->getOperand(0);
50675ffd83dbSDimitry Andric   unsigned Imm2;
5068480093f4SDimitry Andric   // ISD::OR doesn't get all the bitfield insertion fun.
5069480093f4SDimitry Andric   // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) might be a
5070480093f4SDimitry Andric   // bitfield insert.
50715ffd83dbSDimitry Andric   if (Val.getOpcode() != ISD::OR || !isInt32Immediate(Val.getOperand(1), Imm2))
50725ffd83dbSDimitry Andric     return false;
50735ffd83dbSDimitry Andric 
5074480093f4SDimitry Andric   // The idea here is to check whether this is equivalent to:
5075480093f4SDimitry Andric   //   (c1 & m) | (x & ~m)
5076480093f4SDimitry Andric   // where m is a run-of-ones mask. The logic here is that, for each bit in
5077480093f4SDimitry Andric   // c1 and c2:
5078480093f4SDimitry Andric   //  - if both are 1, then the output will be 1.
5079480093f4SDimitry Andric   //  - if both are 0, then the output will be 0.
5080480093f4SDimitry Andric   //  - if the bit in c1 is 0, and the bit in c2 is 1, then the output will
5081480093f4SDimitry Andric   //    come from x.
5082480093f4SDimitry Andric   //  - if the bit in c1 is 1, and the bit in c2 is 0, then the output will
5083480093f4SDimitry Andric   //    be 0.
5084480093f4SDimitry Andric   //  If that last condition is never the case, then we can form m from the
5085480093f4SDimitry Andric   //  bits that are the same between c1 and c2.
5086480093f4SDimitry Andric   unsigned MB, ME;
5087480093f4SDimitry Andric   if (isRunOfOnes(~(Imm ^ Imm2), MB, ME) && !(~Imm & Imm2)) {
50885ffd83dbSDimitry Andric     SDLoc dl(N);
50895ffd83dbSDimitry Andric     SDValue Ops[] = {Val.getOperand(0), Val.getOperand(1), getI32Imm(0, dl),
50905ffd83dbSDimitry Andric                      getI32Imm(MB, dl), getI32Imm(ME, dl)};
5091480093f4SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(PPC::RLWIMI, dl, MVT::i32, Ops));
5092480093f4SDimitry Andric     return true;
5093480093f4SDimitry Andric   }
50945ffd83dbSDimitry Andric 
50955ffd83dbSDimitry Andric   return false;
5096480093f4SDimitry Andric }
50975ffd83dbSDimitry Andric 
tryAsSingleRLDCL(SDNode * N)50985f757f3fSDimitry Andric bool PPCDAGToDAGISel::tryAsSingleRLDCL(SDNode *N) {
50995f757f3fSDimitry Andric   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
51005f757f3fSDimitry Andric 
51015f757f3fSDimitry Andric   uint64_t Imm64;
51025f757f3fSDimitry Andric   if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) || !isMask_64(Imm64))
51035f757f3fSDimitry Andric     return false;
51045f757f3fSDimitry Andric 
51055f757f3fSDimitry Andric   SDValue Val = N->getOperand(0);
51065f757f3fSDimitry Andric 
51075f757f3fSDimitry Andric   if (Val.getOpcode() != ISD::ROTL)
51085f757f3fSDimitry Andric     return false;
51095f757f3fSDimitry Andric 
51105f757f3fSDimitry Andric   // Looking to try to avoid a situation like this one:
51115f757f3fSDimitry Andric   //   %2 = tail call i64 @llvm.fshl.i64(i64 %word, i64 %word, i64 23)
51125f757f3fSDimitry Andric   //   %and1 = and i64 %2, 9223372036854775807
51135f757f3fSDimitry Andric   // In this function we are looking to try to match RLDCL. However, the above
51145f757f3fSDimitry Andric   // DAG would better match RLDICL instead which is not what we are looking
51155f757f3fSDimitry Andric   // for here.
51165f757f3fSDimitry Andric   SDValue RotateAmt = Val.getOperand(1);
51175f757f3fSDimitry Andric   if (RotateAmt.getOpcode() == ISD::Constant)
51185f757f3fSDimitry Andric     return false;
51195f757f3fSDimitry Andric 
51205f757f3fSDimitry Andric   unsigned MB = 64 - llvm::countr_one(Imm64);
51215f757f3fSDimitry Andric   SDLoc dl(N);
51225f757f3fSDimitry Andric   SDValue Ops[] = {Val.getOperand(0), RotateAmt, getI32Imm(MB, dl)};
51235f757f3fSDimitry Andric   CurDAG->SelectNodeTo(N, PPC::RLDCL, MVT::i64, Ops);
51245f757f3fSDimitry Andric   return true;
51255f757f3fSDimitry Andric }
51265f757f3fSDimitry Andric 
tryAsSingleRLDICL(SDNode * N)51275ffd83dbSDimitry Andric bool PPCDAGToDAGISel::tryAsSingleRLDICL(SDNode *N) {
51285ffd83dbSDimitry Andric   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
51295ffd83dbSDimitry Andric   uint64_t Imm64;
51305ffd83dbSDimitry Andric   if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) || !isMask_64(Imm64))
51315ffd83dbSDimitry Andric     return false;
51325ffd83dbSDimitry Andric 
5133480093f4SDimitry Andric   // If this is a 64-bit zero-extension mask, emit rldicl.
513406c3fb27SDimitry Andric   unsigned MB = 64 - llvm::countr_one(Imm64);
51355ffd83dbSDimitry Andric   unsigned SH = 0;
51365ffd83dbSDimitry Andric   unsigned Imm;
51375ffd83dbSDimitry Andric   SDValue Val = N->getOperand(0);
51385ffd83dbSDimitry Andric   SDLoc dl(N);
5139480093f4SDimitry Andric 
5140480093f4SDimitry Andric   if (Val.getOpcode() == ISD::ANY_EXTEND) {
5141480093f4SDimitry Andric     auto Op0 = Val.getOperand(0);
5142480093f4SDimitry Andric     if (Op0.getOpcode() == ISD::SRL &&
5143480093f4SDimitry Andric         isInt32Immediate(Op0.getOperand(1).getNode(), Imm) && Imm <= MB) {
5144480093f4SDimitry Andric 
5145480093f4SDimitry Andric       auto ResultType = Val.getNode()->getValueType(0);
51465ffd83dbSDimitry Andric       auto ImDef = CurDAG->getMachineNode(PPC::IMPLICIT_DEF, dl, ResultType);
5147480093f4SDimitry Andric       SDValue IDVal(ImDef, 0);
5148480093f4SDimitry Andric 
51495ffd83dbSDimitry Andric       Val = SDValue(CurDAG->getMachineNode(PPC::INSERT_SUBREG, dl, ResultType,
51505ffd83dbSDimitry Andric                                            IDVal, Op0.getOperand(0),
51515ffd83dbSDimitry Andric                                            getI32Imm(1, dl)),
51525ffd83dbSDimitry Andric                     0);
5153480093f4SDimitry Andric       SH = 64 - Imm;
5154480093f4SDimitry Andric     }
5155480093f4SDimitry Andric   }
5156480093f4SDimitry Andric 
5157480093f4SDimitry Andric   // If the operand is a logical right shift, we can fold it into this
5158480093f4SDimitry Andric   // instruction: rldicl(rldicl(x, 64-n, n), 0, mb) -> rldicl(x, 64-n, mb)
5159480093f4SDimitry Andric   // for n <= mb. The right shift is really a left rotate followed by a
5160480093f4SDimitry Andric   // mask, and this mask is a more-restrictive sub-mask of the mask implied
5161480093f4SDimitry Andric   // by the shift.
5162480093f4SDimitry Andric   if (Val.getOpcode() == ISD::SRL &&
5163480093f4SDimitry Andric       isInt32Immediate(Val.getOperand(1).getNode(), Imm) && Imm <= MB) {
5164480093f4SDimitry Andric     assert(Imm < 64 && "Illegal shift amount");
5165480093f4SDimitry Andric     Val = Val.getOperand(0);
5166480093f4SDimitry Andric     SH = 64 - Imm;
5167480093f4SDimitry Andric   }
5168480093f4SDimitry Andric 
5169480093f4SDimitry Andric   SDValue Ops[] = {Val, getI32Imm(SH, dl), getI32Imm(MB, dl)};
5170480093f4SDimitry Andric   CurDAG->SelectNodeTo(N, PPC::RLDICL, MVT::i64, Ops);
5171480093f4SDimitry Andric   return true;
51725ffd83dbSDimitry Andric }
51735ffd83dbSDimitry Andric 
tryAsSingleRLDICR(SDNode * N)51745ffd83dbSDimitry Andric bool PPCDAGToDAGISel::tryAsSingleRLDICR(SDNode *N) {
51755ffd83dbSDimitry Andric   assert(N->getOpcode() == ISD::AND && "ISD::AND SDNode expected");
51765ffd83dbSDimitry Andric   uint64_t Imm64;
51775ffd83dbSDimitry Andric   if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) ||
51785ffd83dbSDimitry Andric       !isMask_64(~Imm64))
51795ffd83dbSDimitry Andric     return false;
51805ffd83dbSDimitry Andric 
5181480093f4SDimitry Andric   // If this is a negated 64-bit zero-extension mask,
5182480093f4SDimitry Andric   // i.e. the immediate is a sequence of ones from most significant side
5183480093f4SDimitry Andric   // and all zero for reminder, we should use rldicr.
518406c3fb27SDimitry Andric   unsigned MB = 63 - llvm::countr_one(~Imm64);
51855ffd83dbSDimitry Andric   unsigned SH = 0;
51865ffd83dbSDimitry Andric   SDLoc dl(N);
51875ffd83dbSDimitry Andric   SDValue Ops[] = {N->getOperand(0), getI32Imm(SH, dl), getI32Imm(MB, dl)};
5188480093f4SDimitry Andric   CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, Ops);
5189480093f4SDimitry Andric   return true;
5190480093f4SDimitry Andric }
5191480093f4SDimitry Andric 
tryAsSingleRLDIMI(SDNode * N)51925ffd83dbSDimitry Andric bool PPCDAGToDAGISel::tryAsSingleRLDIMI(SDNode *N) {
51935ffd83dbSDimitry Andric   assert(N->getOpcode() == ISD::OR && "ISD::OR SDNode expected");
51945ffd83dbSDimitry Andric   uint64_t Imm64;
51955ffd83dbSDimitry Andric   unsigned MB, ME;
51965ffd83dbSDimitry Andric   SDValue N0 = N->getOperand(0);
5197480093f4SDimitry Andric 
51985ffd83dbSDimitry Andric   // We won't get fewer instructions if the imm is 32-bit integer.
51995ffd83dbSDimitry Andric   // rldimi requires the imm to have consecutive ones with both sides zero.
52005ffd83dbSDimitry Andric   // Also, make sure the first Op has only one use, otherwise this may increase
52015ffd83dbSDimitry Andric   // register pressure since rldimi is destructive.
52025ffd83dbSDimitry Andric   if (!isInt64Immediate(N->getOperand(1).getNode(), Imm64) ||
52035ffd83dbSDimitry Andric       isUInt<32>(Imm64) || !isRunOfOnes64(Imm64, MB, ME) || !N0.hasOneUse())
5204480093f4SDimitry Andric     return false;
52055ffd83dbSDimitry Andric 
52065ffd83dbSDimitry Andric   unsigned SH = 63 - ME;
52075ffd83dbSDimitry Andric   SDLoc Dl(N);
52085ffd83dbSDimitry Andric   // Use select64Imm for making LI instr instead of directly putting Imm64
52095ffd83dbSDimitry Andric   SDValue Ops[] = {
52105ffd83dbSDimitry Andric       N->getOperand(0),
52115ffd83dbSDimitry Andric       SDValue(selectI64Imm(CurDAG, getI64Imm(-1, Dl).getNode()), 0),
52125ffd83dbSDimitry Andric       getI32Imm(SH, Dl), getI32Imm(MB, Dl)};
52135ffd83dbSDimitry Andric   CurDAG->SelectNodeTo(N, PPC::RLDIMI, MVT::i64, Ops);
52145ffd83dbSDimitry Andric   return true;
5215480093f4SDimitry Andric }
5216480093f4SDimitry Andric 
52170b57cec5SDimitry Andric // Select - Convert the specified operand from a target-independent to a
52180b57cec5SDimitry Andric // target-specific node if it hasn't already been changed.
Select(SDNode * N)52190b57cec5SDimitry Andric void PPCDAGToDAGISel::Select(SDNode *N) {
52200b57cec5SDimitry Andric   SDLoc dl(N);
52210b57cec5SDimitry Andric   if (N->isMachineOpcode()) {
52220b57cec5SDimitry Andric     N->setNodeId(-1);
52230b57cec5SDimitry Andric     return;   // Already selected.
52240b57cec5SDimitry Andric   }
52250b57cec5SDimitry Andric 
52260b57cec5SDimitry Andric   // In case any misguided DAG-level optimizations form an ADD with a
52270b57cec5SDimitry Andric   // TargetConstant operand, crash here instead of miscompiling (by selecting
52280b57cec5SDimitry Andric   // an r+r add instead of some kind of r+i add).
52290b57cec5SDimitry Andric   if (N->getOpcode() == ISD::ADD &&
52300b57cec5SDimitry Andric       N->getOperand(1).getOpcode() == ISD::TargetConstant)
52310b57cec5SDimitry Andric     llvm_unreachable("Invalid ADD with TargetConstant operand");
52320b57cec5SDimitry Andric 
52330b57cec5SDimitry Andric   // Try matching complex bit permutations before doing anything else.
52340b57cec5SDimitry Andric   if (tryBitPermutation(N))
52350b57cec5SDimitry Andric     return;
52360b57cec5SDimitry Andric 
52370b57cec5SDimitry Andric   // Try to emit integer compares as GPR-only sequences (i.e. no use of CR).
52380b57cec5SDimitry Andric   if (tryIntCompareInGPR(N))
52390b57cec5SDimitry Andric     return;
52400b57cec5SDimitry Andric 
52410b57cec5SDimitry Andric   switch (N->getOpcode()) {
52420b57cec5SDimitry Andric   default: break;
52430b57cec5SDimitry Andric 
52440b57cec5SDimitry Andric   case ISD::Constant:
52450b57cec5SDimitry Andric     if (N->getValueType(0) == MVT::i64) {
52460b57cec5SDimitry Andric       ReplaceNode(N, selectI64Imm(CurDAG, N));
52470b57cec5SDimitry Andric       return;
52480b57cec5SDimitry Andric     }
52490b57cec5SDimitry Andric     break;
52500b57cec5SDimitry Andric 
5251349cc55cSDimitry Andric   case ISD::INTRINSIC_VOID: {
5252349cc55cSDimitry Andric     auto IntrinsicID = N->getConstantOperandVal(1);
5253bdd1243dSDimitry Andric     if (IntrinsicID != Intrinsic::ppc_tdw && IntrinsicID != Intrinsic::ppc_tw &&
5254bdd1243dSDimitry Andric         IntrinsicID != Intrinsic::ppc_trapd &&
5255bdd1243dSDimitry Andric         IntrinsicID != Intrinsic::ppc_trap)
5256bdd1243dSDimitry Andric         break;
5257bdd1243dSDimitry Andric     unsigned Opcode = (IntrinsicID == Intrinsic::ppc_tdw ||
5258bdd1243dSDimitry Andric                        IntrinsicID == Intrinsic::ppc_trapd)
5259bdd1243dSDimitry Andric                           ? PPC::TDI
5260bdd1243dSDimitry Andric                           : PPC::TWI;
5261bdd1243dSDimitry Andric     SmallVector<SDValue, 4> OpsWithMD;
5262bdd1243dSDimitry Andric     unsigned MDIndex;
5263bdd1243dSDimitry Andric     if (IntrinsicID == Intrinsic::ppc_tdw ||
5264bdd1243dSDimitry Andric         IntrinsicID == Intrinsic::ppc_tw) {
5265349cc55cSDimitry Andric       SDValue Ops[] = {N->getOperand(4), N->getOperand(2), N->getOperand(3)};
5266349cc55cSDimitry Andric       int16_t SImmOperand2;
5267349cc55cSDimitry Andric       int16_t SImmOperand3;
5268349cc55cSDimitry Andric       int16_t SImmOperand4;
5269349cc55cSDimitry Andric       bool isOperand2IntS16Immediate =
5270349cc55cSDimitry Andric           isIntS16Immediate(N->getOperand(2), SImmOperand2);
5271349cc55cSDimitry Andric       bool isOperand3IntS16Immediate =
5272349cc55cSDimitry Andric           isIntS16Immediate(N->getOperand(3), SImmOperand3);
5273349cc55cSDimitry Andric       // We will emit PPC::TD or PPC::TW if the 2nd and 3rd operands are reg +
5274349cc55cSDimitry Andric       // reg or imm + imm. The imm + imm form will be optimized to either an
5275349cc55cSDimitry Andric       // unconditional trap or a nop in a later pass.
5276349cc55cSDimitry Andric       if (isOperand2IntS16Immediate == isOperand3IntS16Immediate)
5277349cc55cSDimitry Andric         Opcode = IntrinsicID == Intrinsic::ppc_tdw ? PPC::TD : PPC::TW;
5278349cc55cSDimitry Andric       else if (isOperand3IntS16Immediate)
5279349cc55cSDimitry Andric         // The 2nd and 3rd operands are reg + imm.
5280349cc55cSDimitry Andric         Ops[2] = getI32Imm(int(SImmOperand3) & 0xFFFF, dl);
5281349cc55cSDimitry Andric       else {
5282349cc55cSDimitry Andric         // The 2nd and 3rd operands are imm + reg.
5283349cc55cSDimitry Andric         bool isOperand4IntS16Immediate =
5284349cc55cSDimitry Andric             isIntS16Immediate(N->getOperand(4), SImmOperand4);
5285349cc55cSDimitry Andric         (void)isOperand4IntS16Immediate;
5286349cc55cSDimitry Andric         assert(isOperand4IntS16Immediate &&
5287349cc55cSDimitry Andric                "The 4th operand is not an Immediate");
5288349cc55cSDimitry Andric         // We need to flip the condition immediate TO.
5289349cc55cSDimitry Andric         int16_t TO = int(SImmOperand4) & 0x1F;
5290349cc55cSDimitry Andric         // We swap the first and second bit of TO if they are not same.
5291349cc55cSDimitry Andric         if ((TO & 0x1) != ((TO & 0x2) >> 1))
5292349cc55cSDimitry Andric           TO = (TO & 0x1) ? TO + 1 : TO - 1;
5293349cc55cSDimitry Andric         // We swap the fourth and fifth bit of TO if they are not same.
5294349cc55cSDimitry Andric         if ((TO & 0x8) != ((TO & 0x10) >> 1))
5295349cc55cSDimitry Andric           TO = (TO & 0x8) ? TO + 8 : TO - 8;
5296349cc55cSDimitry Andric         Ops[0] = getI32Imm(TO, dl);
5297349cc55cSDimitry Andric         Ops[1] = N->getOperand(3);
5298349cc55cSDimitry Andric         Ops[2] = getI32Imm(int(SImmOperand2) & 0xFFFF, dl);
5299349cc55cSDimitry Andric       }
5300bdd1243dSDimitry Andric       OpsWithMD = {Ops[0], Ops[1], Ops[2]};
5301bdd1243dSDimitry Andric       MDIndex = 5;
5302bdd1243dSDimitry Andric     } else {
5303bdd1243dSDimitry Andric       OpsWithMD = {getI32Imm(24, dl), N->getOperand(2), getI32Imm(0, dl)};
5304bdd1243dSDimitry Andric       MDIndex = 3;
5305349cc55cSDimitry Andric     }
5306bdd1243dSDimitry Andric 
5307bdd1243dSDimitry Andric     if (N->getNumOperands() > MDIndex) {
5308bdd1243dSDimitry Andric       SDValue MDV = N->getOperand(MDIndex);
5309bdd1243dSDimitry Andric       const MDNode *MD = cast<MDNodeSDNode>(MDV)->getMD();
5310bdd1243dSDimitry Andric       assert(MD->getNumOperands() != 0 && "Empty MDNode in operands!");
5311*0fca6ea1SDimitry Andric       assert((isa<MDString>(MD->getOperand(0)) &&
5312*0fca6ea1SDimitry Andric               cast<MDString>(MD->getOperand(0))->getString() ==
5313*0fca6ea1SDimitry Andric                   "ppc-trap-reason") &&
5314*0fca6ea1SDimitry Andric              "Unsupported annotation data type!");
5315bdd1243dSDimitry Andric       for (unsigned i = 1; i < MD->getNumOperands(); i++) {
5316bdd1243dSDimitry Andric         assert(isa<MDString>(MD->getOperand(i)) &&
5317bdd1243dSDimitry Andric                "Invalid data type for annotation ppc-trap-reason!");
5318bdd1243dSDimitry Andric         OpsWithMD.push_back(
5319bdd1243dSDimitry Andric             getI32Imm(std::stoi(cast<MDString>(
5320bdd1243dSDimitry Andric                       MD->getOperand(i))->getString().str()), dl));
5321bdd1243dSDimitry Andric       }
5322bdd1243dSDimitry Andric     }
5323bdd1243dSDimitry Andric     OpsWithMD.push_back(N->getOperand(0)); // chain
5324bdd1243dSDimitry Andric     CurDAG->SelectNodeTo(N, Opcode, MVT::Other, OpsWithMD);
5325bdd1243dSDimitry Andric     return;
5326349cc55cSDimitry Andric   }
5327349cc55cSDimitry Andric 
5328e8d8bef9SDimitry Andric   case ISD::INTRINSIC_WO_CHAIN: {
5329fe6060f1SDimitry Andric     // We emit the PPC::FSELS instruction here because of type conflicts with
5330fe6060f1SDimitry Andric     // the comparison operand. The FSELS instruction is defined to use an 8-byte
5331fe6060f1SDimitry Andric     // comparison like the FSELD version. The fsels intrinsic takes a 4-byte
5332fe6060f1SDimitry Andric     // value for the comparison. When selecting through a .td file, a type
5333fe6060f1SDimitry Andric     // error is raised. Must check this first so we never break on the
5334fe6060f1SDimitry Andric     // !Subtarget->isISA3_1() check.
53354824e7fdSDimitry Andric     auto IntID = N->getConstantOperandVal(0);
53364824e7fdSDimitry Andric     if (IntID == Intrinsic::ppc_fsels) {
5337fe6060f1SDimitry Andric       SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3)};
5338fe6060f1SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::FSELS, MVT::f32, Ops);
5339fe6060f1SDimitry Andric       return;
5340fe6060f1SDimitry Andric     }
5341fe6060f1SDimitry Andric 
53424824e7fdSDimitry Andric     if (IntID == Intrinsic::ppc_bcdadd_p || IntID == Intrinsic::ppc_bcdsub_p) {
53434824e7fdSDimitry Andric       auto Pred = N->getConstantOperandVal(1);
53444824e7fdSDimitry Andric       unsigned Opcode =
53454824e7fdSDimitry Andric           IntID == Intrinsic::ppc_bcdadd_p ? PPC::BCDADD_rec : PPC::BCDSUB_rec;
53464824e7fdSDimitry Andric       unsigned SubReg = 0;
53474824e7fdSDimitry Andric       unsigned ShiftVal = 0;
53484824e7fdSDimitry Andric       bool Reverse = false;
53494824e7fdSDimitry Andric       switch (Pred) {
53504824e7fdSDimitry Andric       case 0:
53514824e7fdSDimitry Andric         SubReg = PPC::sub_eq;
53524824e7fdSDimitry Andric         ShiftVal = 1;
53534824e7fdSDimitry Andric         break;
53544824e7fdSDimitry Andric       case 1:
53554824e7fdSDimitry Andric         SubReg = PPC::sub_eq;
53564824e7fdSDimitry Andric         ShiftVal = 1;
53574824e7fdSDimitry Andric         Reverse = true;
53584824e7fdSDimitry Andric         break;
53594824e7fdSDimitry Andric       case 2:
53604824e7fdSDimitry Andric         SubReg = PPC::sub_lt;
53614824e7fdSDimitry Andric         ShiftVal = 3;
53624824e7fdSDimitry Andric         break;
53634824e7fdSDimitry Andric       case 3:
53644824e7fdSDimitry Andric         SubReg = PPC::sub_lt;
53654824e7fdSDimitry Andric         ShiftVal = 3;
53664824e7fdSDimitry Andric         Reverse = true;
53674824e7fdSDimitry Andric         break;
53684824e7fdSDimitry Andric       case 4:
53694824e7fdSDimitry Andric         SubReg = PPC::sub_gt;
53704824e7fdSDimitry Andric         ShiftVal = 2;
53714824e7fdSDimitry Andric         break;
53724824e7fdSDimitry Andric       case 5:
53734824e7fdSDimitry Andric         SubReg = PPC::sub_gt;
53744824e7fdSDimitry Andric         ShiftVal = 2;
53754824e7fdSDimitry Andric         Reverse = true;
53764824e7fdSDimitry Andric         break;
53774824e7fdSDimitry Andric       case 6:
53784824e7fdSDimitry Andric         SubReg = PPC::sub_un;
53794824e7fdSDimitry Andric         break;
53804824e7fdSDimitry Andric       case 7:
53814824e7fdSDimitry Andric         SubReg = PPC::sub_un;
53824824e7fdSDimitry Andric         Reverse = true;
53834824e7fdSDimitry Andric         break;
53844824e7fdSDimitry Andric       }
53854824e7fdSDimitry Andric 
53864824e7fdSDimitry Andric       EVT VTs[] = {MVT::v16i8, MVT::Glue};
53874824e7fdSDimitry Andric       SDValue Ops[] = {N->getOperand(2), N->getOperand(3),
53884824e7fdSDimitry Andric                        CurDAG->getTargetConstant(0, dl, MVT::i32)};
53894824e7fdSDimitry Andric       SDValue BCDOp = SDValue(CurDAG->getMachineNode(Opcode, dl, VTs, Ops), 0);
53904824e7fdSDimitry Andric       SDValue CR6Reg = CurDAG->getRegister(PPC::CR6, MVT::i32);
53914824e7fdSDimitry Andric       // On Power10, we can use SETBC[R]. On prior architectures, we have to use
53924824e7fdSDimitry Andric       // MFOCRF and shift/negate the value.
53934824e7fdSDimitry Andric       if (Subtarget->isISA3_1()) {
53944824e7fdSDimitry Andric         SDValue SubRegIdx = CurDAG->getTargetConstant(SubReg, dl, MVT::i32);
53954824e7fdSDimitry Andric         SDValue CRBit = SDValue(
53964824e7fdSDimitry Andric             CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::i1,
53974824e7fdSDimitry Andric                                    CR6Reg, SubRegIdx, BCDOp.getValue(1)),
53984824e7fdSDimitry Andric             0);
53994824e7fdSDimitry Andric         CurDAG->SelectNodeTo(N, Reverse ? PPC::SETBCR : PPC::SETBC, MVT::i32,
54004824e7fdSDimitry Andric                              CRBit);
54014824e7fdSDimitry Andric       } else {
54024824e7fdSDimitry Andric         SDValue Move =
54034824e7fdSDimitry Andric             SDValue(CurDAG->getMachineNode(PPC::MFOCRF, dl, MVT::i32, CR6Reg,
54044824e7fdSDimitry Andric                                            BCDOp.getValue(1)),
54054824e7fdSDimitry Andric                     0);
54064824e7fdSDimitry Andric         SDValue Ops[] = {Move, getI32Imm((32 - (4 + ShiftVal)) & 31, dl),
54074824e7fdSDimitry Andric                          getI32Imm(31, dl), getI32Imm(31, dl)};
54084824e7fdSDimitry Andric         if (!Reverse)
54094824e7fdSDimitry Andric           CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
54104824e7fdSDimitry Andric         else {
54114824e7fdSDimitry Andric           SDValue Shift = SDValue(
54124824e7fdSDimitry Andric               CurDAG->getMachineNode(PPC::RLWINM, dl, MVT::i32, Ops), 0);
54134824e7fdSDimitry Andric           CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Shift, getI32Imm(1, dl));
54144824e7fdSDimitry Andric         }
54154824e7fdSDimitry Andric       }
54164824e7fdSDimitry Andric       return;
54174824e7fdSDimitry Andric     }
54184824e7fdSDimitry Andric 
5419e8d8bef9SDimitry Andric     if (!Subtarget->isISA3_1())
5420e8d8bef9SDimitry Andric       break;
5421e8d8bef9SDimitry Andric     unsigned Opcode = 0;
54224824e7fdSDimitry Andric     switch (IntID) {
5423e8d8bef9SDimitry Andric     default:
5424e8d8bef9SDimitry Andric       break;
5425e8d8bef9SDimitry Andric     case Intrinsic::ppc_altivec_vstribr_p:
5426e8d8bef9SDimitry Andric       Opcode = PPC::VSTRIBR_rec;
5427e8d8bef9SDimitry Andric       break;
5428e8d8bef9SDimitry Andric     case Intrinsic::ppc_altivec_vstribl_p:
5429e8d8bef9SDimitry Andric       Opcode = PPC::VSTRIBL_rec;
5430e8d8bef9SDimitry Andric       break;
5431e8d8bef9SDimitry Andric     case Intrinsic::ppc_altivec_vstrihr_p:
5432e8d8bef9SDimitry Andric       Opcode = PPC::VSTRIHR_rec;
5433e8d8bef9SDimitry Andric       break;
5434e8d8bef9SDimitry Andric     case Intrinsic::ppc_altivec_vstrihl_p:
5435e8d8bef9SDimitry Andric       Opcode = PPC::VSTRIHL_rec;
5436e8d8bef9SDimitry Andric       break;
5437e8d8bef9SDimitry Andric     }
5438e8d8bef9SDimitry Andric     if (!Opcode)
5439e8d8bef9SDimitry Andric       break;
5440e8d8bef9SDimitry Andric 
5441e8d8bef9SDimitry Andric     // Generate the appropriate vector string isolate intrinsic to match.
5442e8d8bef9SDimitry Andric     EVT VTs[] = {MVT::v16i8, MVT::Glue};
5443e8d8bef9SDimitry Andric     SDValue VecStrOp =
5444e8d8bef9SDimitry Andric         SDValue(CurDAG->getMachineNode(Opcode, dl, VTs, N->getOperand(2)), 0);
5445e8d8bef9SDimitry Andric     // Vector string isolate instructions update the EQ bit of CR6.
5446e8d8bef9SDimitry Andric     // Generate a SETBC instruction to extract the bit and place it in a GPR.
5447e8d8bef9SDimitry Andric     SDValue SubRegIdx = CurDAG->getTargetConstant(PPC::sub_eq, dl, MVT::i32);
5448e8d8bef9SDimitry Andric     SDValue CR6Reg = CurDAG->getRegister(PPC::CR6, MVT::i32);
5449e8d8bef9SDimitry Andric     SDValue CRBit = SDValue(
5450e8d8bef9SDimitry Andric         CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG, dl, MVT::i1,
5451e8d8bef9SDimitry Andric                                CR6Reg, SubRegIdx, VecStrOp.getValue(1)),
5452e8d8bef9SDimitry Andric         0);
5453e8d8bef9SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::SETBC, MVT::i32, CRBit);
5454e8d8bef9SDimitry Andric     return;
5455e8d8bef9SDimitry Andric   }
5456e8d8bef9SDimitry Andric 
54570b57cec5SDimitry Andric   case ISD::SETCC:
5458e8d8bef9SDimitry Andric   case ISD::STRICT_FSETCC:
5459e8d8bef9SDimitry Andric   case ISD::STRICT_FSETCCS:
54600b57cec5SDimitry Andric     if (trySETCC(N))
54610b57cec5SDimitry Andric       return;
54620b57cec5SDimitry Andric     break;
54630b57cec5SDimitry Andric   // These nodes will be transformed into GETtlsADDR32 node, which
54640b57cec5SDimitry Andric   // later becomes BL_TLS __tls_get_addr(sym at tlsgd)@PLT
54650b57cec5SDimitry Andric   case PPCISD::ADDI_TLSLD_L_ADDR:
54660b57cec5SDimitry Andric   case PPCISD::ADDI_TLSGD_L_ADDR: {
54670b57cec5SDimitry Andric     const Module *Mod = MF->getFunction().getParent();
54680b57cec5SDimitry Andric     if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 ||
54695ffd83dbSDimitry Andric         !Subtarget->isSecurePlt() || !Subtarget->isTargetELF() ||
54700b57cec5SDimitry Andric         Mod->getPICLevel() == PICLevel::SmallPIC)
54710b57cec5SDimitry Andric       break;
54720b57cec5SDimitry Andric     // Attach global base pointer on GETtlsADDR32 node in order to
54730b57cec5SDimitry Andric     // generate secure plt code for TLS symbols.
54740b57cec5SDimitry Andric     getGlobalBaseReg();
54750b57cec5SDimitry Andric   } break;
54760b57cec5SDimitry Andric   case PPCISD::CALL: {
54770b57cec5SDimitry Andric     if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 ||
54785ffd83dbSDimitry Andric         !TM.isPositionIndependent() || !Subtarget->isSecurePlt() ||
54795ffd83dbSDimitry Andric         !Subtarget->isTargetELF())
54800b57cec5SDimitry Andric       break;
54810b57cec5SDimitry Andric 
54820b57cec5SDimitry Andric     SDValue Op = N->getOperand(1);
54830b57cec5SDimitry Andric 
54840b57cec5SDimitry Andric     if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) {
54850b57cec5SDimitry Andric       if (GA->getTargetFlags() == PPCII::MO_PLT)
54860b57cec5SDimitry Andric         getGlobalBaseReg();
54870b57cec5SDimitry Andric     }
54880b57cec5SDimitry Andric     else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) {
54890b57cec5SDimitry Andric       if (ES->getTargetFlags() == PPCII::MO_PLT)
54900b57cec5SDimitry Andric         getGlobalBaseReg();
54910b57cec5SDimitry Andric     }
54920b57cec5SDimitry Andric   }
54930b57cec5SDimitry Andric     break;
54940b57cec5SDimitry Andric 
54950b57cec5SDimitry Andric   case PPCISD::GlobalBaseReg:
54960b57cec5SDimitry Andric     ReplaceNode(N, getGlobalBaseReg());
54970b57cec5SDimitry Andric     return;
54980b57cec5SDimitry Andric 
54990b57cec5SDimitry Andric   case ISD::FrameIndex:
55000b57cec5SDimitry Andric     selectFrameIndex(N, N);
55010b57cec5SDimitry Andric     return;
55020b57cec5SDimitry Andric 
55030b57cec5SDimitry Andric   case PPCISD::MFOCRF: {
550406c3fb27SDimitry Andric     SDValue InGlue = N->getOperand(1);
55050b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(PPC::MFOCRF, dl, MVT::i32,
550606c3fb27SDimitry Andric                                           N->getOperand(0), InGlue));
55070b57cec5SDimitry Andric     return;
55080b57cec5SDimitry Andric   }
55090b57cec5SDimitry Andric 
55100b57cec5SDimitry Andric   case PPCISD::READ_TIME_BASE:
55110b57cec5SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(PPC::ReadTB, dl, MVT::i32, MVT::i32,
55120b57cec5SDimitry Andric                                           MVT::Other, N->getOperand(0)));
55130b57cec5SDimitry Andric     return;
55140b57cec5SDimitry Andric 
55150b57cec5SDimitry Andric   case PPCISD::SRA_ADDZE: {
55160b57cec5SDimitry Andric     SDValue N0 = N->getOperand(0);
55170b57cec5SDimitry Andric     SDValue ShiftAmt =
55180b57cec5SDimitry Andric       CurDAG->getTargetConstant(*cast<ConstantSDNode>(N->getOperand(1))->
55190b57cec5SDimitry Andric                                   getConstantIntValue(), dl,
55200b57cec5SDimitry Andric                                   N->getValueType(0));
55210b57cec5SDimitry Andric     if (N->getValueType(0) == MVT::i64) {
55220b57cec5SDimitry Andric       SDNode *Op =
55230b57cec5SDimitry Andric         CurDAG->getMachineNode(PPC::SRADI, dl, MVT::i64, MVT::Glue,
55240b57cec5SDimitry Andric                                N0, ShiftAmt);
55250b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::ADDZE8, MVT::i64, SDValue(Op, 0),
55260b57cec5SDimitry Andric                            SDValue(Op, 1));
55270b57cec5SDimitry Andric       return;
55280b57cec5SDimitry Andric     } else {
55290b57cec5SDimitry Andric       assert(N->getValueType(0) == MVT::i32 &&
55300b57cec5SDimitry Andric              "Expecting i64 or i32 in PPCISD::SRA_ADDZE");
55310b57cec5SDimitry Andric       SDNode *Op =
55320b57cec5SDimitry Andric         CurDAG->getMachineNode(PPC::SRAWI, dl, MVT::i32, MVT::Glue,
55330b57cec5SDimitry Andric                                N0, ShiftAmt);
55340b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, SDValue(Op, 0),
55350b57cec5SDimitry Andric                            SDValue(Op, 1));
55360b57cec5SDimitry Andric       return;
55370b57cec5SDimitry Andric     }
55380b57cec5SDimitry Andric   }
55390b57cec5SDimitry Andric 
55400b57cec5SDimitry Andric   case ISD::STORE: {
554106c3fb27SDimitry Andric     // Change TLS initial-exec (or TLS local-exec on AIX) D-form stores to
554206c3fb27SDimitry Andric     // X-form stores.
55430b57cec5SDimitry Andric     StoreSDNode *ST = cast<StoreSDNode>(N);
554406c3fb27SDimitry Andric     if (EnableTLSOpt && (Subtarget->isELFv2ABI() || Subtarget->isAIXABI()) &&
55450b57cec5SDimitry Andric         ST->getAddressingMode() != ISD::PRE_INC)
55460b57cec5SDimitry Andric       if (tryTLSXFormStore(ST))
55470b57cec5SDimitry Andric         return;
55480b57cec5SDimitry Andric     break;
55490b57cec5SDimitry Andric   }
55500b57cec5SDimitry Andric   case ISD::LOAD: {
55510b57cec5SDimitry Andric     // Handle preincrement loads.
55520b57cec5SDimitry Andric     LoadSDNode *LD = cast<LoadSDNode>(N);
55530b57cec5SDimitry Andric     EVT LoadedVT = LD->getMemoryVT();
55540b57cec5SDimitry Andric 
55550b57cec5SDimitry Andric     // Normal loads are handled by code generated from the .td file.
55560b57cec5SDimitry Andric     if (LD->getAddressingMode() != ISD::PRE_INC) {
555706c3fb27SDimitry Andric       // Change TLS initial-exec (or TLS local-exec on AIX) D-form loads to
555806c3fb27SDimitry Andric       // X-form loads.
555906c3fb27SDimitry Andric       if (EnableTLSOpt && (Subtarget->isELFv2ABI() || Subtarget->isAIXABI()))
55600b57cec5SDimitry Andric         if (tryTLSXFormLoad(LD))
55610b57cec5SDimitry Andric           return;
55620b57cec5SDimitry Andric       break;
55630b57cec5SDimitry Andric     }
55640b57cec5SDimitry Andric 
55650b57cec5SDimitry Andric     SDValue Offset = LD->getOffset();
55660b57cec5SDimitry Andric     if (Offset.getOpcode() == ISD::TargetConstant ||
55670b57cec5SDimitry Andric         Offset.getOpcode() == ISD::TargetGlobalAddress) {
55680b57cec5SDimitry Andric 
55690b57cec5SDimitry Andric       unsigned Opcode;
55700b57cec5SDimitry Andric       bool isSExt = LD->getExtensionType() == ISD::SEXTLOAD;
55710b57cec5SDimitry Andric       if (LD->getValueType(0) != MVT::i64) {
55720b57cec5SDimitry Andric         // Handle PPC32 integer and normal FP loads.
55730b57cec5SDimitry Andric         assert((!isSExt || LoadedVT == MVT::i16) && "Invalid sext update load");
55740b57cec5SDimitry Andric         switch (LoadedVT.getSimpleVT().SimpleTy) {
55750b57cec5SDimitry Andric           default: llvm_unreachable("Invalid PPC load type!");
55760b57cec5SDimitry Andric           case MVT::f64: Opcode = PPC::LFDU; break;
55770b57cec5SDimitry Andric           case MVT::f32: Opcode = PPC::LFSU; break;
55780b57cec5SDimitry Andric           case MVT::i32: Opcode = PPC::LWZU; break;
55790b57cec5SDimitry Andric           case MVT::i16: Opcode = isSExt ? PPC::LHAU : PPC::LHZU; break;
55800b57cec5SDimitry Andric           case MVT::i1:
55810b57cec5SDimitry Andric           case MVT::i8:  Opcode = PPC::LBZU; break;
55820b57cec5SDimitry Andric         }
55830b57cec5SDimitry Andric       } else {
55840b57cec5SDimitry Andric         assert(LD->getValueType(0) == MVT::i64 && "Unknown load result type!");
55850b57cec5SDimitry Andric         assert((!isSExt || LoadedVT == MVT::i16) && "Invalid sext update load");
55860b57cec5SDimitry Andric         switch (LoadedVT.getSimpleVT().SimpleTy) {
55870b57cec5SDimitry Andric           default: llvm_unreachable("Invalid PPC load type!");
55880b57cec5SDimitry Andric           case MVT::i64: Opcode = PPC::LDU; break;
55890b57cec5SDimitry Andric           case MVT::i32: Opcode = PPC::LWZU8; break;
55900b57cec5SDimitry Andric           case MVT::i16: Opcode = isSExt ? PPC::LHAU8 : PPC::LHZU8; break;
55910b57cec5SDimitry Andric           case MVT::i1:
55920b57cec5SDimitry Andric           case MVT::i8:  Opcode = PPC::LBZU8; break;
55930b57cec5SDimitry Andric         }
55940b57cec5SDimitry Andric       }
55950b57cec5SDimitry Andric 
55960b57cec5SDimitry Andric       SDValue Chain = LD->getChain();
55970b57cec5SDimitry Andric       SDValue Base = LD->getBasePtr();
55980b57cec5SDimitry Andric       SDValue Ops[] = { Offset, Base, Chain };
55990b57cec5SDimitry Andric       SDNode *MN = CurDAG->getMachineNode(
56000b57cec5SDimitry Andric           Opcode, dl, LD->getValueType(0),
56010b57cec5SDimitry Andric           PPCLowering->getPointerTy(CurDAG->getDataLayout()), MVT::Other, Ops);
56020b57cec5SDimitry Andric       transferMemOperands(N, MN);
56030b57cec5SDimitry Andric       ReplaceNode(N, MN);
56040b57cec5SDimitry Andric       return;
56050b57cec5SDimitry Andric     } else {
56060b57cec5SDimitry Andric       unsigned Opcode;
56070b57cec5SDimitry Andric       bool isSExt = LD->getExtensionType() == ISD::SEXTLOAD;
56080b57cec5SDimitry Andric       if (LD->getValueType(0) != MVT::i64) {
56090b57cec5SDimitry Andric         // Handle PPC32 integer and normal FP loads.
56100b57cec5SDimitry Andric         assert((!isSExt || LoadedVT == MVT::i16) && "Invalid sext update load");
56110b57cec5SDimitry Andric         switch (LoadedVT.getSimpleVT().SimpleTy) {
56120b57cec5SDimitry Andric           default: llvm_unreachable("Invalid PPC load type!");
56130b57cec5SDimitry Andric           case MVT::f64: Opcode = PPC::LFDUX; break;
56140b57cec5SDimitry Andric           case MVT::f32: Opcode = PPC::LFSUX; break;
56150b57cec5SDimitry Andric           case MVT::i32: Opcode = PPC::LWZUX; break;
56160b57cec5SDimitry Andric           case MVT::i16: Opcode = isSExt ? PPC::LHAUX : PPC::LHZUX; break;
56170b57cec5SDimitry Andric           case MVT::i1:
56180b57cec5SDimitry Andric           case MVT::i8:  Opcode = PPC::LBZUX; break;
56190b57cec5SDimitry Andric         }
56200b57cec5SDimitry Andric       } else {
56210b57cec5SDimitry Andric         assert(LD->getValueType(0) == MVT::i64 && "Unknown load result type!");
56220b57cec5SDimitry Andric         assert((!isSExt || LoadedVT == MVT::i16 || LoadedVT == MVT::i32) &&
56230b57cec5SDimitry Andric                "Invalid sext update load");
56240b57cec5SDimitry Andric         switch (LoadedVT.getSimpleVT().SimpleTy) {
56250b57cec5SDimitry Andric           default: llvm_unreachable("Invalid PPC load type!");
56260b57cec5SDimitry Andric           case MVT::i64: Opcode = PPC::LDUX; break;
56270b57cec5SDimitry Andric           case MVT::i32: Opcode = isSExt ? PPC::LWAUX  : PPC::LWZUX8; break;
56280b57cec5SDimitry Andric           case MVT::i16: Opcode = isSExt ? PPC::LHAUX8 : PPC::LHZUX8; break;
56290b57cec5SDimitry Andric           case MVT::i1:
56300b57cec5SDimitry Andric           case MVT::i8:  Opcode = PPC::LBZUX8; break;
56310b57cec5SDimitry Andric         }
56320b57cec5SDimitry Andric       }
56330b57cec5SDimitry Andric 
56340b57cec5SDimitry Andric       SDValue Chain = LD->getChain();
56350b57cec5SDimitry Andric       SDValue Base = LD->getBasePtr();
56360b57cec5SDimitry Andric       SDValue Ops[] = { Base, Offset, Chain };
56370b57cec5SDimitry Andric       SDNode *MN = CurDAG->getMachineNode(
56380b57cec5SDimitry Andric           Opcode, dl, LD->getValueType(0),
56390b57cec5SDimitry Andric           PPCLowering->getPointerTy(CurDAG->getDataLayout()), MVT::Other, Ops);
56400b57cec5SDimitry Andric       transferMemOperands(N, MN);
56410b57cec5SDimitry Andric       ReplaceNode(N, MN);
56420b57cec5SDimitry Andric       return;
56430b57cec5SDimitry Andric     }
56440b57cec5SDimitry Andric   }
56450b57cec5SDimitry Andric 
5646480093f4SDimitry Andric   case ISD::AND:
5647480093f4SDimitry Andric     // If this is an 'and' with a mask, try to emit rlwinm/rldicl/rldicr
56485f757f3fSDimitry Andric     if (tryAsSingleRLWINM(N) || tryAsSingleRLWIMI(N) || tryAsSingleRLDCL(N) ||
56495f757f3fSDimitry Andric         tryAsSingleRLDICL(N) || tryAsSingleRLDICR(N) || tryAsSingleRLWINM8(N) ||
56505f757f3fSDimitry Andric         tryAsPairOfRLDICL(N))
56510b57cec5SDimitry Andric       return;
56520b57cec5SDimitry Andric 
56530b57cec5SDimitry Andric     // Other cases are autogenerated.
56540b57cec5SDimitry Andric     break;
56550b57cec5SDimitry Andric   case ISD::OR: {
56560b57cec5SDimitry Andric     if (N->getValueType(0) == MVT::i32)
56570b57cec5SDimitry Andric       if (tryBitfieldInsert(N))
56580b57cec5SDimitry Andric         return;
56590b57cec5SDimitry Andric 
56600b57cec5SDimitry Andric     int16_t Imm;
56610b57cec5SDimitry Andric     if (N->getOperand(0)->getOpcode() == ISD::FrameIndex &&
56620b57cec5SDimitry Andric         isIntS16Immediate(N->getOperand(1), Imm)) {
56630b57cec5SDimitry Andric       KnownBits LHSKnown = CurDAG->computeKnownBits(N->getOperand(0));
56640b57cec5SDimitry Andric 
56650b57cec5SDimitry Andric       // If this is equivalent to an add, then we can fold it with the
56660b57cec5SDimitry Andric       // FrameIndex calculation.
56670b57cec5SDimitry Andric       if ((LHSKnown.Zero.getZExtValue()|~(uint64_t)Imm) == ~0ULL) {
566881ad6265SDimitry Andric         selectFrameIndex(N, N->getOperand(0).getNode(), (int64_t)Imm);
56690b57cec5SDimitry Andric         return;
56700b57cec5SDimitry Andric       }
56710b57cec5SDimitry Andric     }
56720b57cec5SDimitry Andric 
56735ffd83dbSDimitry Andric     // If this is 'or' against an imm with consecutive ones and both sides zero,
56745ffd83dbSDimitry Andric     // try to emit rldimi
56755ffd83dbSDimitry Andric     if (tryAsSingleRLDIMI(N))
56765ffd83dbSDimitry Andric       return;
56775ffd83dbSDimitry Andric 
56780b57cec5SDimitry Andric     // OR with a 32-bit immediate can be handled by ori + oris
56790b57cec5SDimitry Andric     // without creating an immediate in a GPR.
56800b57cec5SDimitry Andric     uint64_t Imm64 = 0;
56815ffd83dbSDimitry Andric     bool IsPPC64 = Subtarget->isPPC64();
56820b57cec5SDimitry Andric     if (IsPPC64 && isInt64Immediate(N->getOperand(1), Imm64) &&
56830b57cec5SDimitry Andric         (Imm64 & ~0xFFFFFFFFuLL) == 0) {
56840b57cec5SDimitry Andric       // If ImmHi (ImmHi) is zero, only one ori (oris) is generated later.
56850b57cec5SDimitry Andric       uint64_t ImmHi = Imm64 >> 16;
56860b57cec5SDimitry Andric       uint64_t ImmLo = Imm64 & 0xFFFF;
56870b57cec5SDimitry Andric       if (ImmHi != 0 && ImmLo != 0) {
56880b57cec5SDimitry Andric         SDNode *Lo = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64,
56890b57cec5SDimitry Andric                                             N->getOperand(0),
56900b57cec5SDimitry Andric                                             getI16Imm(ImmLo, dl));
56910b57cec5SDimitry Andric         SDValue Ops1[] = { SDValue(Lo, 0), getI16Imm(ImmHi, dl)};
56920b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::ORIS8, MVT::i64, Ops1);
56930b57cec5SDimitry Andric         return;
56940b57cec5SDimitry Andric       }
56950b57cec5SDimitry Andric     }
56960b57cec5SDimitry Andric 
56970b57cec5SDimitry Andric     // Other cases are autogenerated.
56980b57cec5SDimitry Andric     break;
56990b57cec5SDimitry Andric   }
57000b57cec5SDimitry Andric   case ISD::XOR: {
57010b57cec5SDimitry Andric     // XOR with a 32-bit immediate can be handled by xori + xoris
57020b57cec5SDimitry Andric     // without creating an immediate in a GPR.
57030b57cec5SDimitry Andric     uint64_t Imm64 = 0;
57045ffd83dbSDimitry Andric     bool IsPPC64 = Subtarget->isPPC64();
57050b57cec5SDimitry Andric     if (IsPPC64 && isInt64Immediate(N->getOperand(1), Imm64) &&
57060b57cec5SDimitry Andric         (Imm64 & ~0xFFFFFFFFuLL) == 0) {
57070b57cec5SDimitry Andric       // If ImmHi (ImmHi) is zero, only one xori (xoris) is generated later.
57080b57cec5SDimitry Andric       uint64_t ImmHi = Imm64 >> 16;
57090b57cec5SDimitry Andric       uint64_t ImmLo = Imm64 & 0xFFFF;
57100b57cec5SDimitry Andric       if (ImmHi != 0 && ImmLo != 0) {
57110b57cec5SDimitry Andric         SDNode *Lo = CurDAG->getMachineNode(PPC::XORI8, dl, MVT::i64,
57120b57cec5SDimitry Andric                                             N->getOperand(0),
57130b57cec5SDimitry Andric                                             getI16Imm(ImmLo, dl));
57140b57cec5SDimitry Andric         SDValue Ops1[] = { SDValue(Lo, 0), getI16Imm(ImmHi, dl)};
57150b57cec5SDimitry Andric         CurDAG->SelectNodeTo(N, PPC::XORIS8, MVT::i64, Ops1);
57160b57cec5SDimitry Andric         return;
57170b57cec5SDimitry Andric       }
57180b57cec5SDimitry Andric     }
57190b57cec5SDimitry Andric 
57200b57cec5SDimitry Andric     break;
57210b57cec5SDimitry Andric   }
57220b57cec5SDimitry Andric   case ISD::ADD: {
57230b57cec5SDimitry Andric     int16_t Imm;
57240b57cec5SDimitry Andric     if (N->getOperand(0)->getOpcode() == ISD::FrameIndex &&
57250b57cec5SDimitry Andric         isIntS16Immediate(N->getOperand(1), Imm)) {
572681ad6265SDimitry Andric       selectFrameIndex(N, N->getOperand(0).getNode(), (int64_t)Imm);
57270b57cec5SDimitry Andric       return;
57280b57cec5SDimitry Andric     }
57290b57cec5SDimitry Andric 
57300b57cec5SDimitry Andric     break;
57310b57cec5SDimitry Andric   }
57320b57cec5SDimitry Andric   case ISD::SHL: {
57330b57cec5SDimitry Andric     unsigned Imm, SH, MB, ME;
57340b57cec5SDimitry Andric     if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, Imm) &&
57350b57cec5SDimitry Andric         isRotateAndMask(N, Imm, true, SH, MB, ME)) {
57360b57cec5SDimitry Andric       SDValue Ops[] = { N->getOperand(0).getOperand(0),
57370b57cec5SDimitry Andric                           getI32Imm(SH, dl), getI32Imm(MB, dl),
57380b57cec5SDimitry Andric                           getI32Imm(ME, dl) };
57390b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
57400b57cec5SDimitry Andric       return;
57410b57cec5SDimitry Andric     }
57420b57cec5SDimitry Andric 
57430b57cec5SDimitry Andric     // Other cases are autogenerated.
57440b57cec5SDimitry Andric     break;
57450b57cec5SDimitry Andric   }
57460b57cec5SDimitry Andric   case ISD::SRL: {
57470b57cec5SDimitry Andric     unsigned Imm, SH, MB, ME;
57480b57cec5SDimitry Andric     if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::AND, Imm) &&
57490b57cec5SDimitry Andric         isRotateAndMask(N, Imm, true, SH, MB, ME)) {
57500b57cec5SDimitry Andric       SDValue Ops[] = { N->getOperand(0).getOperand(0),
57510b57cec5SDimitry Andric                           getI32Imm(SH, dl), getI32Imm(MB, dl),
57520b57cec5SDimitry Andric                           getI32Imm(ME, dl) };
57530b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
57540b57cec5SDimitry Andric       return;
57550b57cec5SDimitry Andric     }
57560b57cec5SDimitry Andric 
57570b57cec5SDimitry Andric     // Other cases are autogenerated.
57580b57cec5SDimitry Andric     break;
57590b57cec5SDimitry Andric   }
5760e8d8bef9SDimitry Andric   case ISD::MUL: {
5761e8d8bef9SDimitry Andric     SDValue Op1 = N->getOperand(1);
5762fcaf7f86SDimitry Andric     if (Op1.getOpcode() != ISD::Constant ||
5763fcaf7f86SDimitry Andric         (Op1.getValueType() != MVT::i64 && Op1.getValueType() != MVT::i32))
5764e8d8bef9SDimitry Andric       break;
5765e8d8bef9SDimitry Andric 
5766e8d8bef9SDimitry Andric     // If the multiplier fits int16, we can handle it with mulli.
57671db9f3b2SDimitry Andric     int64_t Imm = Op1->getAsZExtVal();
576806c3fb27SDimitry Andric     unsigned Shift = llvm::countr_zero<uint64_t>(Imm);
5769e8d8bef9SDimitry Andric     if (isInt<16>(Imm) || !Shift)
5770e8d8bef9SDimitry Andric       break;
5771e8d8bef9SDimitry Andric 
5772e8d8bef9SDimitry Andric     // If the shifted value fits int16, we can do this transformation:
5773e8d8bef9SDimitry Andric     // (mul X, c1 << c2) -> (rldicr (mulli X, c1) c2). We do this in ISEL due to
5774e8d8bef9SDimitry Andric     // DAGCombiner prefers (shl (mul X, c1), c2) -> (mul X, c1 << c2).
5775e8d8bef9SDimitry Andric     uint64_t ImmSh = Imm >> Shift;
5776fcaf7f86SDimitry Andric     if (!isInt<16>(ImmSh))
5777fcaf7f86SDimitry Andric       break;
5778fcaf7f86SDimitry Andric 
5779e8d8bef9SDimitry Andric     uint64_t SextImm = SignExtend64(ImmSh & 0xFFFF, 16);
5780fcaf7f86SDimitry Andric     if (Op1.getValueType() == MVT::i64) {
5781e8d8bef9SDimitry Andric       SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i64);
5782e8d8bef9SDimitry Andric       SDNode *MulNode = CurDAG->getMachineNode(PPC::MULLI8, dl, MVT::i64,
5783e8d8bef9SDimitry Andric                                                N->getOperand(0), SDImm);
5784fcaf7f86SDimitry Andric 
5785fcaf7f86SDimitry Andric       SDValue Ops[] = {SDValue(MulNode, 0), getI32Imm(Shift, dl),
5786fcaf7f86SDimitry Andric                        getI32Imm(63 - Shift, dl)};
5787fcaf7f86SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, Ops);
5788fcaf7f86SDimitry Andric       return;
5789fcaf7f86SDimitry Andric     } else {
5790fcaf7f86SDimitry Andric       SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i32);
5791fcaf7f86SDimitry Andric       SDNode *MulNode = CurDAG->getMachineNode(PPC::MULLI, dl, MVT::i32,
5792fcaf7f86SDimitry Andric                                               N->getOperand(0), SDImm);
5793fcaf7f86SDimitry Andric 
5794fcaf7f86SDimitry Andric       SDValue Ops[] = {SDValue(MulNode, 0), getI32Imm(Shift, dl),
5795fcaf7f86SDimitry Andric                        getI32Imm(0, dl), getI32Imm(31 - Shift, dl)};
5796fcaf7f86SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops);
5797e8d8bef9SDimitry Andric       return;
5798e8d8bef9SDimitry Andric     }
5799e8d8bef9SDimitry Andric     break;
5800e8d8bef9SDimitry Andric   }
58010b57cec5SDimitry Andric   // FIXME: Remove this once the ANDI glue bug is fixed:
5802480093f4SDimitry Andric   case PPCISD::ANDI_rec_1_EQ_BIT:
5803480093f4SDimitry Andric   case PPCISD::ANDI_rec_1_GT_BIT: {
58040b57cec5SDimitry Andric     if (!ANDIGlueBug)
58050b57cec5SDimitry Andric       break;
58060b57cec5SDimitry Andric 
58070b57cec5SDimitry Andric     EVT InVT = N->getOperand(0).getValueType();
58080b57cec5SDimitry Andric     assert((InVT == MVT::i64 || InVT == MVT::i32) &&
5809480093f4SDimitry Andric            "Invalid input type for ANDI_rec_1_EQ_BIT");
58100b57cec5SDimitry Andric 
5811480093f4SDimitry Andric     unsigned Opcode = (InVT == MVT::i64) ? PPC::ANDI8_rec : PPC::ANDI_rec;
58120b57cec5SDimitry Andric     SDValue AndI(CurDAG->getMachineNode(Opcode, dl, InVT, MVT::Glue,
58130b57cec5SDimitry Andric                                         N->getOperand(0),
58140b57cec5SDimitry Andric                                         CurDAG->getTargetConstant(1, dl, InVT)),
58150b57cec5SDimitry Andric                  0);
58160b57cec5SDimitry Andric     SDValue CR0Reg = CurDAG->getRegister(PPC::CR0, MVT::i32);
5817480093f4SDimitry Andric     SDValue SRIdxVal = CurDAG->getTargetConstant(
5818480093f4SDimitry Andric         N->getOpcode() == PPCISD::ANDI_rec_1_EQ_BIT ? PPC::sub_eq : PPC::sub_gt,
5819480093f4SDimitry Andric         dl, MVT::i32);
58200b57cec5SDimitry Andric 
58210b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, TargetOpcode::EXTRACT_SUBREG, MVT::i1, CR0Reg,
58220b57cec5SDimitry Andric                          SRIdxVal, SDValue(AndI.getNode(), 1) /* glue */);
58230b57cec5SDimitry Andric     return;
58240b57cec5SDimitry Andric   }
58250b57cec5SDimitry Andric   case ISD::SELECT_CC: {
58260b57cec5SDimitry Andric     ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get();
58270b57cec5SDimitry Andric     EVT PtrVT =
58280b57cec5SDimitry Andric         CurDAG->getTargetLoweringInfo().getPointerTy(CurDAG->getDataLayout());
58290b57cec5SDimitry Andric     bool isPPC64 = (PtrVT == MVT::i64);
58300b57cec5SDimitry Andric 
58310b57cec5SDimitry Andric     // If this is a select of i1 operands, we'll pattern match it.
58325ffd83dbSDimitry Andric     if (Subtarget->useCRBits() && N->getOperand(0).getValueType() == MVT::i1)
58330b57cec5SDimitry Andric       break;
58340b57cec5SDimitry Andric 
58355ffd83dbSDimitry Andric     if (Subtarget->isISA3_0() && Subtarget->isPPC64()) {
58360b57cec5SDimitry Andric       bool NeedSwapOps = false;
58370b57cec5SDimitry Andric       bool IsUnCmp = false;
58380b57cec5SDimitry Andric       if (mayUseP9Setb(N, CC, CurDAG, NeedSwapOps, IsUnCmp)) {
58390b57cec5SDimitry Andric         SDValue LHS = N->getOperand(0);
58400b57cec5SDimitry Andric         SDValue RHS = N->getOperand(1);
58410b57cec5SDimitry Andric         if (NeedSwapOps)
58420b57cec5SDimitry Andric           std::swap(LHS, RHS);
58430b57cec5SDimitry Andric 
58440b57cec5SDimitry Andric         // Make use of SelectCC to generate the comparison to set CR bits, for
58450b57cec5SDimitry Andric         // equality comparisons having one literal operand, SelectCC probably
58460b57cec5SDimitry Andric         // doesn't need to materialize the whole literal and just use xoris to
58470b57cec5SDimitry Andric         // check it first, it leads the following comparison result can't
58480b57cec5SDimitry Andric         // exactly represent GT/LT relationship. So to avoid this we specify
58490b57cec5SDimitry Andric         // SETGT/SETUGT here instead of SETEQ.
58500b57cec5SDimitry Andric         SDValue GenCC =
58510b57cec5SDimitry Andric             SelectCC(LHS, RHS, IsUnCmp ? ISD::SETUGT : ISD::SETGT, dl);
58520b57cec5SDimitry Andric         CurDAG->SelectNodeTo(
58530b57cec5SDimitry Andric             N, N->getSimpleValueType(0) == MVT::i64 ? PPC::SETB8 : PPC::SETB,
58540b57cec5SDimitry Andric             N->getValueType(0), GenCC);
58550b57cec5SDimitry Andric         NumP9Setb++;
58560b57cec5SDimitry Andric         return;
58570b57cec5SDimitry Andric       }
58580b57cec5SDimitry Andric     }
58590b57cec5SDimitry Andric 
58600b57cec5SDimitry Andric     // Handle the setcc cases here.  select_cc lhs, 0, 1, 0, cc
586106c3fb27SDimitry Andric     if (!isPPC64 && isNullConstant(N->getOperand(1)) &&
586206c3fb27SDimitry Andric         isOneConstant(N->getOperand(2)) && isNullConstant(N->getOperand(3)) &&
5863349cc55cSDimitry Andric         CC == ISD::SETNE &&
58640b57cec5SDimitry Andric         // FIXME: Implement this optzn for PPC64.
58650b57cec5SDimitry Andric         N->getValueType(0) == MVT::i32) {
58660b57cec5SDimitry Andric       SDNode *Tmp =
58670b57cec5SDimitry Andric           CurDAG->getMachineNode(PPC::ADDIC, dl, MVT::i32, MVT::Glue,
58680b57cec5SDimitry Andric                                  N->getOperand(0), getI32Imm(~0U, dl));
58690b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, SDValue(Tmp, 0),
58700b57cec5SDimitry Andric                            N->getOperand(0), SDValue(Tmp, 1));
58710b57cec5SDimitry Andric       return;
58720b57cec5SDimitry Andric     }
58730b57cec5SDimitry Andric 
58740b57cec5SDimitry Andric     SDValue CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC, dl);
58750b57cec5SDimitry Andric 
58760b57cec5SDimitry Andric     if (N->getValueType(0) == MVT::i1) {
58770b57cec5SDimitry Andric       // An i1 select is: (c & t) | (!c & f).
58780b57cec5SDimitry Andric       bool Inv;
58790b57cec5SDimitry Andric       unsigned Idx = getCRIdxForSetCC(CC, Inv);
58800b57cec5SDimitry Andric 
58810b57cec5SDimitry Andric       unsigned SRI;
58820b57cec5SDimitry Andric       switch (Idx) {
58830b57cec5SDimitry Andric       default: llvm_unreachable("Invalid CC index");
58840b57cec5SDimitry Andric       case 0: SRI = PPC::sub_lt; break;
58850b57cec5SDimitry Andric       case 1: SRI = PPC::sub_gt; break;
58860b57cec5SDimitry Andric       case 2: SRI = PPC::sub_eq; break;
58870b57cec5SDimitry Andric       case 3: SRI = PPC::sub_un; break;
58880b57cec5SDimitry Andric       }
58890b57cec5SDimitry Andric 
58900b57cec5SDimitry Andric       SDValue CCBit = CurDAG->getTargetExtractSubreg(SRI, dl, MVT::i1, CCReg);
58910b57cec5SDimitry Andric 
58920b57cec5SDimitry Andric       SDValue NotCCBit(CurDAG->getMachineNode(PPC::CRNOR, dl, MVT::i1,
58930b57cec5SDimitry Andric                                               CCBit, CCBit), 0);
58940b57cec5SDimitry Andric       SDValue C =    Inv ? NotCCBit : CCBit,
58950b57cec5SDimitry Andric               NotC = Inv ? CCBit    : NotCCBit;
58960b57cec5SDimitry Andric 
58970b57cec5SDimitry Andric       SDValue CAndT(CurDAG->getMachineNode(PPC::CRAND, dl, MVT::i1,
58980b57cec5SDimitry Andric                                            C, N->getOperand(2)), 0);
58990b57cec5SDimitry Andric       SDValue NotCAndF(CurDAG->getMachineNode(PPC::CRAND, dl, MVT::i1,
59000b57cec5SDimitry Andric                                               NotC, N->getOperand(3)), 0);
59010b57cec5SDimitry Andric 
59020b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::CROR, MVT::i1, CAndT, NotCAndF);
59030b57cec5SDimitry Andric       return;
59040b57cec5SDimitry Andric     }
59050b57cec5SDimitry Andric 
5906480093f4SDimitry Andric     unsigned BROpc =
59075ffd83dbSDimitry Andric         getPredicateForSetCC(CC, N->getOperand(0).getValueType(), Subtarget);
59080b57cec5SDimitry Andric 
59090b57cec5SDimitry Andric     unsigned SelectCCOp;
59100b57cec5SDimitry Andric     if (N->getValueType(0) == MVT::i32)
59110b57cec5SDimitry Andric       SelectCCOp = PPC::SELECT_CC_I4;
59120b57cec5SDimitry Andric     else if (N->getValueType(0) == MVT::i64)
59130b57cec5SDimitry Andric       SelectCCOp = PPC::SELECT_CC_I8;
59140b57cec5SDimitry Andric     else if (N->getValueType(0) == MVT::f32) {
59155ffd83dbSDimitry Andric       if (Subtarget->hasP8Vector())
59160b57cec5SDimitry Andric         SelectCCOp = PPC::SELECT_CC_VSSRC;
59175ffd83dbSDimitry Andric       else if (Subtarget->hasSPE())
59180b57cec5SDimitry Andric         SelectCCOp = PPC::SELECT_CC_SPE4;
59190b57cec5SDimitry Andric       else
59200b57cec5SDimitry Andric         SelectCCOp = PPC::SELECT_CC_F4;
59210b57cec5SDimitry Andric     } else if (N->getValueType(0) == MVT::f64) {
59225ffd83dbSDimitry Andric       if (Subtarget->hasVSX())
59230b57cec5SDimitry Andric         SelectCCOp = PPC::SELECT_CC_VSFRC;
59245ffd83dbSDimitry Andric       else if (Subtarget->hasSPE())
59250b57cec5SDimitry Andric         SelectCCOp = PPC::SELECT_CC_SPE;
59260b57cec5SDimitry Andric       else
59270b57cec5SDimitry Andric         SelectCCOp = PPC::SELECT_CC_F8;
59280b57cec5SDimitry Andric     } else if (N->getValueType(0) == MVT::f128)
59290b57cec5SDimitry Andric       SelectCCOp = PPC::SELECT_CC_F16;
59305ffd83dbSDimitry Andric     else if (Subtarget->hasSPE())
59310b57cec5SDimitry Andric       SelectCCOp = PPC::SELECT_CC_SPE;
59320b57cec5SDimitry Andric     else if (N->getValueType(0) == MVT::v2f64 ||
59330b57cec5SDimitry Andric              N->getValueType(0) == MVT::v2i64)
59340b57cec5SDimitry Andric       SelectCCOp = PPC::SELECT_CC_VSRC;
59350b57cec5SDimitry Andric     else
59360b57cec5SDimitry Andric       SelectCCOp = PPC::SELECT_CC_VRRC;
59370b57cec5SDimitry Andric 
59380b57cec5SDimitry Andric     SDValue Ops[] = { CCReg, N->getOperand(2), N->getOperand(3),
59390b57cec5SDimitry Andric                         getI32Imm(BROpc, dl) };
59400b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, SelectCCOp, N->getValueType(0), Ops);
59410b57cec5SDimitry Andric     return;
59420b57cec5SDimitry Andric   }
59430b57cec5SDimitry Andric   case ISD::VECTOR_SHUFFLE:
59445ffd83dbSDimitry Andric     if (Subtarget->hasVSX() && (N->getValueType(0) == MVT::v2f64 ||
59450b57cec5SDimitry Andric                                 N->getValueType(0) == MVT::v2i64)) {
59460b57cec5SDimitry Andric       ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(N);
59470b57cec5SDimitry Andric 
59480b57cec5SDimitry Andric       SDValue Op1 = N->getOperand(SVN->getMaskElt(0) < 2 ? 0 : 1),
59490b57cec5SDimitry Andric               Op2 = N->getOperand(SVN->getMaskElt(1) < 2 ? 0 : 1);
59500b57cec5SDimitry Andric       unsigned DM[2];
59510b57cec5SDimitry Andric 
59520b57cec5SDimitry Andric       for (int i = 0; i < 2; ++i)
59530b57cec5SDimitry Andric         if (SVN->getMaskElt(i) <= 0 || SVN->getMaskElt(i) == 2)
59540b57cec5SDimitry Andric           DM[i] = 0;
59550b57cec5SDimitry Andric         else
59560b57cec5SDimitry Andric           DM[i] = 1;
59570b57cec5SDimitry Andric 
59580b57cec5SDimitry Andric       if (Op1 == Op2 && DM[0] == 0 && DM[1] == 0 &&
59590b57cec5SDimitry Andric           Op1.getOpcode() == ISD::SCALAR_TO_VECTOR &&
59600b57cec5SDimitry Andric           isa<LoadSDNode>(Op1.getOperand(0))) {
59610b57cec5SDimitry Andric         LoadSDNode *LD = cast<LoadSDNode>(Op1.getOperand(0));
59620b57cec5SDimitry Andric         SDValue Base, Offset;
59630b57cec5SDimitry Andric 
59640b57cec5SDimitry Andric         if (LD->isUnindexed() && LD->hasOneUse() && Op1.hasOneUse() &&
59650b57cec5SDimitry Andric             (LD->getMemoryVT() == MVT::f64 ||
59660b57cec5SDimitry Andric              LD->getMemoryVT() == MVT::i64) &&
59670b57cec5SDimitry Andric             SelectAddrIdxOnly(LD->getBasePtr(), Base, Offset)) {
59680b57cec5SDimitry Andric           SDValue Chain = LD->getChain();
59690b57cec5SDimitry Andric           SDValue Ops[] = { Base, Offset, Chain };
59700b57cec5SDimitry Andric           MachineMemOperand *MemOp = LD->getMemOperand();
59710b57cec5SDimitry Andric           SDNode *NewN = CurDAG->SelectNodeTo(N, PPC::LXVDSX,
59720b57cec5SDimitry Andric                                               N->getValueType(0), Ops);
59730b57cec5SDimitry Andric           CurDAG->setNodeMemRefs(cast<MachineSDNode>(NewN), {MemOp});
59740b57cec5SDimitry Andric           return;
59750b57cec5SDimitry Andric         }
59760b57cec5SDimitry Andric       }
59770b57cec5SDimitry Andric 
59780b57cec5SDimitry Andric       // For little endian, we must swap the input operands and adjust
59790b57cec5SDimitry Andric       // the mask elements (reverse and invert them).
59805ffd83dbSDimitry Andric       if (Subtarget->isLittleEndian()) {
59810b57cec5SDimitry Andric         std::swap(Op1, Op2);
59820b57cec5SDimitry Andric         unsigned tmp = DM[0];
59830b57cec5SDimitry Andric         DM[0] = 1 - DM[1];
59840b57cec5SDimitry Andric         DM[1] = 1 - tmp;
59850b57cec5SDimitry Andric       }
59860b57cec5SDimitry Andric 
59870b57cec5SDimitry Andric       SDValue DMV = CurDAG->getTargetConstant(DM[1] | (DM[0] << 1), dl,
59880b57cec5SDimitry Andric                                               MVT::i32);
59890b57cec5SDimitry Andric       SDValue Ops[] = { Op1, Op2, DMV };
59900b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::XXPERMDI, N->getValueType(0), Ops);
59910b57cec5SDimitry Andric       return;
59920b57cec5SDimitry Andric     }
59930b57cec5SDimitry Andric 
59940b57cec5SDimitry Andric     break;
59950b57cec5SDimitry Andric   case PPCISD::BDNZ:
59960b57cec5SDimitry Andric   case PPCISD::BDZ: {
59975ffd83dbSDimitry Andric     bool IsPPC64 = Subtarget->isPPC64();
59980b57cec5SDimitry Andric     SDValue Ops[] = { N->getOperand(1), N->getOperand(0) };
59990b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, N->getOpcode() == PPCISD::BDNZ
60000b57cec5SDimitry Andric                                 ? (IsPPC64 ? PPC::BDNZ8 : PPC::BDNZ)
60010b57cec5SDimitry Andric                                 : (IsPPC64 ? PPC::BDZ8 : PPC::BDZ),
60020b57cec5SDimitry Andric                          MVT::Other, Ops);
60030b57cec5SDimitry Andric     return;
60040b57cec5SDimitry Andric   }
60050b57cec5SDimitry Andric   case PPCISD::COND_BRANCH: {
60060b57cec5SDimitry Andric     // Op #0 is the Chain.
60070b57cec5SDimitry Andric     // Op #1 is the PPC::PRED_* number.
60080b57cec5SDimitry Andric     // Op #2 is the CR#
60090b57cec5SDimitry Andric     // Op #3 is the Dest MBB
60100b57cec5SDimitry Andric     // Op #4 is the Flag.
60110b57cec5SDimitry Andric     // Prevent PPC::PRED_* from being selected into LI.
6012647cbc5dSDimitry Andric     unsigned PCC = N->getConstantOperandVal(1);
60130b57cec5SDimitry Andric     if (EnableBranchHint)
6014480093f4SDimitry Andric       PCC |= getBranchHint(PCC, *FuncInfo, N->getOperand(3));
60150b57cec5SDimitry Andric 
60160b57cec5SDimitry Andric     SDValue Pred = getI32Imm(PCC, dl);
60170b57cec5SDimitry Andric     SDValue Ops[] = { Pred, N->getOperand(2), N->getOperand(3),
60180b57cec5SDimitry Andric       N->getOperand(0), N->getOperand(4) };
60190b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops);
60200b57cec5SDimitry Andric     return;
60210b57cec5SDimitry Andric   }
60220b57cec5SDimitry Andric   case ISD::BR_CC: {
6023e8d8bef9SDimitry Andric     if (tryFoldSWTestBRCC(N))
6024e8d8bef9SDimitry Andric       return;
6025bdd1243dSDimitry Andric     if (trySelectLoopCountIntrinsic(N))
6026bdd1243dSDimitry Andric       return;
60270b57cec5SDimitry Andric     ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get();
6028480093f4SDimitry Andric     unsigned PCC =
60295ffd83dbSDimitry Andric         getPredicateForSetCC(CC, N->getOperand(2).getValueType(), Subtarget);
60300b57cec5SDimitry Andric 
60310b57cec5SDimitry Andric     if (N->getOperand(2).getValueType() == MVT::i1) {
60320b57cec5SDimitry Andric       unsigned Opc;
60330b57cec5SDimitry Andric       bool Swap;
60340b57cec5SDimitry Andric       switch (PCC) {
60350b57cec5SDimitry Andric       default: llvm_unreachable("Unexpected Boolean-operand predicate");
60360b57cec5SDimitry Andric       case PPC::PRED_LT: Opc = PPC::CRANDC; Swap = true;  break;
60370b57cec5SDimitry Andric       case PPC::PRED_LE: Opc = PPC::CRORC;  Swap = true;  break;
60380b57cec5SDimitry Andric       case PPC::PRED_EQ: Opc = PPC::CREQV;  Swap = false; break;
60390b57cec5SDimitry Andric       case PPC::PRED_GE: Opc = PPC::CRORC;  Swap = false; break;
60400b57cec5SDimitry Andric       case PPC::PRED_GT: Opc = PPC::CRANDC; Swap = false; break;
60410b57cec5SDimitry Andric       case PPC::PRED_NE: Opc = PPC::CRXOR;  Swap = false; break;
60420b57cec5SDimitry Andric       }
60430b57cec5SDimitry Andric 
60440b57cec5SDimitry Andric       // A signed comparison of i1 values produces the opposite result to an
60450b57cec5SDimitry Andric       // unsigned one if the condition code includes less-than or greater-than.
60460b57cec5SDimitry Andric       // This is because 1 is the most negative signed i1 number and the most
60470b57cec5SDimitry Andric       // positive unsigned i1 number. The CR-logical operations used for such
60480b57cec5SDimitry Andric       // comparisons are non-commutative so for signed comparisons vs. unsigned
60490b57cec5SDimitry Andric       // ones, the input operands just need to be swapped.
60500b57cec5SDimitry Andric       if (ISD::isSignedIntSetCC(CC))
60510b57cec5SDimitry Andric         Swap = !Swap;
60520b57cec5SDimitry Andric 
60530b57cec5SDimitry Andric       SDValue BitComp(CurDAG->getMachineNode(Opc, dl, MVT::i1,
60540b57cec5SDimitry Andric                                              N->getOperand(Swap ? 3 : 2),
60550b57cec5SDimitry Andric                                              N->getOperand(Swap ? 2 : 3)), 0);
60560b57cec5SDimitry Andric       CurDAG->SelectNodeTo(N, PPC::BC, MVT::Other, BitComp, N->getOperand(4),
60570b57cec5SDimitry Andric                            N->getOperand(0));
60580b57cec5SDimitry Andric       return;
60590b57cec5SDimitry Andric     }
60600b57cec5SDimitry Andric 
60610b57cec5SDimitry Andric     if (EnableBranchHint)
6062480093f4SDimitry Andric       PCC |= getBranchHint(PCC, *FuncInfo, N->getOperand(4));
60630b57cec5SDimitry Andric 
60640b57cec5SDimitry Andric     SDValue CondCode = SelectCC(N->getOperand(2), N->getOperand(3), CC, dl);
60650b57cec5SDimitry Andric     SDValue Ops[] = { getI32Imm(PCC, dl), CondCode,
60660b57cec5SDimitry Andric                         N->getOperand(4), N->getOperand(0) };
60670b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops);
60680b57cec5SDimitry Andric     return;
60690b57cec5SDimitry Andric   }
60700b57cec5SDimitry Andric   case ISD::BRIND: {
60710b57cec5SDimitry Andric     // FIXME: Should custom lower this.
60720b57cec5SDimitry Andric     SDValue Chain = N->getOperand(0);
60730b57cec5SDimitry Andric     SDValue Target = N->getOperand(1);
60740b57cec5SDimitry Andric     unsigned Opc = Target.getValueType() == MVT::i32 ? PPC::MTCTR : PPC::MTCTR8;
60750b57cec5SDimitry Andric     unsigned Reg = Target.getValueType() == MVT::i32 ? PPC::BCTR : PPC::BCTR8;
60760b57cec5SDimitry Andric     Chain = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Glue, Target,
60770b57cec5SDimitry Andric                                            Chain), 0);
60780b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, Reg, MVT::Other, Chain);
60790b57cec5SDimitry Andric     return;
60800b57cec5SDimitry Andric   }
60810b57cec5SDimitry Andric   case PPCISD::TOC_ENTRY: {
60825ffd83dbSDimitry Andric     const bool isPPC64 = Subtarget->isPPC64();
60835ffd83dbSDimitry Andric     const bool isELFABI = Subtarget->isSVR4ABI();
60845ffd83dbSDimitry Andric     const bool isAIXABI = Subtarget->isAIXABI();
60858bcb0991SDimitry Andric 
60868bcb0991SDimitry Andric     // PowerPC only support small, medium and large code model.
6087*0fca6ea1SDimitry Andric     const CodeModel::Model CModel = getCodeModel(*Subtarget, TM, N);
6088*0fca6ea1SDimitry Andric 
60898bcb0991SDimitry Andric     assert(!(CModel == CodeModel::Tiny || CModel == CodeModel::Kernel) &&
60908bcb0991SDimitry Andric            "PowerPC doesn't support tiny or kernel code models.");
60918bcb0991SDimitry Andric 
60928bcb0991SDimitry Andric     if (isAIXABI && CModel == CodeModel::Medium)
60938bcb0991SDimitry Andric       report_fatal_error("Medium code model is not supported on AIX.");
60948bcb0991SDimitry Andric 
60954824e7fdSDimitry Andric     // For 64-bit ELF small code model, we allow SelectCodeCommon to handle
60964824e7fdSDimitry Andric     // this, selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA. For AIX
60974824e7fdSDimitry Andric     // small code model, we need to check for a toc-data attribute.
60984824e7fdSDimitry Andric     if (isPPC64 && !isAIXABI && CModel == CodeModel::Small)
60990b57cec5SDimitry Andric       break;
61000b57cec5SDimitry Andric 
61014824e7fdSDimitry Andric     auto replaceWith = [this, &dl](unsigned OpCode, SDNode *TocEntry,
61024824e7fdSDimitry Andric                                    EVT OperandTy) {
61038bcb0991SDimitry Andric       SDValue GA = TocEntry->getOperand(0);
61048bcb0991SDimitry Andric       SDValue TocBase = TocEntry->getOperand(1);
6105*0fca6ea1SDimitry Andric       SDNode *MN = nullptr;
6106*0fca6ea1SDimitry Andric       if (OpCode == PPC::ADDItoc || OpCode == PPC::ADDItoc8)
6107*0fca6ea1SDimitry Andric         // toc-data access doesn't involve in loading from got, no need to
6108*0fca6ea1SDimitry Andric         // keep memory operands.
6109*0fca6ea1SDimitry Andric         MN = CurDAG->getMachineNode(OpCode, dl, OperandTy, TocBase, GA);
6110*0fca6ea1SDimitry Andric       else {
6111*0fca6ea1SDimitry Andric         MN = CurDAG->getMachineNode(OpCode, dl, OperandTy, GA, TocBase);
61128bcb0991SDimitry Andric         transferMemOperands(TocEntry, MN);
6113*0fca6ea1SDimitry Andric       }
61148bcb0991SDimitry Andric       ReplaceNode(TocEntry, MN);
61158bcb0991SDimitry Andric     };
61168bcb0991SDimitry Andric 
61174824e7fdSDimitry Andric     // Handle 32-bit small code model.
61184824e7fdSDimitry Andric     if (!isPPC64 && CModel == CodeModel::Small) {
61194824e7fdSDimitry Andric       // Transforms the ISD::TOC_ENTRY node to passed in Opcode, either
61204824e7fdSDimitry Andric       // PPC::ADDItoc, or PPC::LWZtoc
61218bcb0991SDimitry Andric       if (isELFABI) {
61228bcb0991SDimitry Andric         assert(TM.isPositionIndependent() &&
61238bcb0991SDimitry Andric                "32-bit ELF can only have TOC entries in position independent"
61248bcb0991SDimitry Andric                " code.");
61258bcb0991SDimitry Andric         // 32-bit ELF always uses a small code model toc access.
61264824e7fdSDimitry Andric         replaceWith(PPC::LWZtoc, N, MVT::i32);
61278bcb0991SDimitry Andric         return;
61288bcb0991SDimitry Andric       }
61298bcb0991SDimitry Andric 
61304824e7fdSDimitry Andric       assert(isAIXABI && "ELF ABI already handled");
61314824e7fdSDimitry Andric 
6132*0fca6ea1SDimitry Andric       if (hasTocDataAttr(N->getOperand(0))) {
61334824e7fdSDimitry Andric         replaceWith(PPC::ADDItoc, N, MVT::i32);
61348bcb0991SDimitry Andric         return;
61358bcb0991SDimitry Andric       }
61364824e7fdSDimitry Andric 
61374824e7fdSDimitry Andric       replaceWith(PPC::LWZtoc, N, MVT::i32);
61384824e7fdSDimitry Andric       return;
61394824e7fdSDimitry Andric     }
61404824e7fdSDimitry Andric 
61414824e7fdSDimitry Andric     if (isPPC64 && CModel == CodeModel::Small) {
61424824e7fdSDimitry Andric       assert(isAIXABI && "ELF ABI handled in common SelectCode");
61434824e7fdSDimitry Andric 
6144*0fca6ea1SDimitry Andric       if (hasTocDataAttr(N->getOperand(0))) {
61454824e7fdSDimitry Andric         replaceWith(PPC::ADDItoc8, N, MVT::i64);
61464824e7fdSDimitry Andric         return;
61474824e7fdSDimitry Andric       }
61484824e7fdSDimitry Andric       // Break if it doesn't have toc data attribute. Proceed with common
61494824e7fdSDimitry Andric       // SelectCode.
61504824e7fdSDimitry Andric       break;
61518bcb0991SDimitry Andric     }
61528bcb0991SDimitry Andric 
61538bcb0991SDimitry Andric     assert(CModel != CodeModel::Small && "All small code models handled.");
61548bcb0991SDimitry Andric 
61558bcb0991SDimitry Andric     assert((isPPC64 || (isAIXABI && !isPPC64)) && "We are dealing with 64-bit"
61568bcb0991SDimitry Andric            " ELF/AIX or 32-bit AIX in the following.");
61578bcb0991SDimitry Andric 
6158*0fca6ea1SDimitry Andric     // Transforms the ISD::TOC_ENTRY node for 32-bit AIX large code model mode,
6159*0fca6ea1SDimitry Andric     // 64-bit medium (ELF-only), or 64-bit large (ELF and AIX) code model code
6160*0fca6ea1SDimitry Andric     // that does not contain TOC data symbols. We generate two instructions as
6161*0fca6ea1SDimitry Andric     // described below. The first source operand is a symbol reference. If it
6162*0fca6ea1SDimitry Andric     // must be referenced via the TOC according to Subtarget, we generate:
61638bcb0991SDimitry Andric     // [32-bit AIX]
61648bcb0991SDimitry Andric     //   LWZtocL(@sym, ADDIStocHA(%r2, @sym))
61658bcb0991SDimitry Andric     // [64-bit ELF/AIX]
61668bcb0991SDimitry Andric     //   LDtocL(@sym, ADDIStocHA8(%x2, @sym))
6167*0fca6ea1SDimitry Andric     // Otherwise for medium code model ELF we generate:
6168*0fca6ea1SDimitry Andric     //   ADDItocL8(ADDIStocHA8(%x2, @sym), @sym)
6169*0fca6ea1SDimitry Andric 
6170*0fca6ea1SDimitry Andric     // And finally for AIX with toc-data we generate:
6171*0fca6ea1SDimitry Andric     // [32-bit AIX]
6172*0fca6ea1SDimitry Andric     //   ADDItocL(ADDIStocHA(%x2, @sym), @sym)
6173*0fca6ea1SDimitry Andric     // [64-bit AIX]
6174*0fca6ea1SDimitry Andric     //   ADDItocL8(ADDIStocHA8(%x2, @sym), @sym)
6175*0fca6ea1SDimitry Andric 
61760b57cec5SDimitry Andric     SDValue GA = N->getOperand(0);
61770b57cec5SDimitry Andric     SDValue TOCbase = N->getOperand(1);
61788bcb0991SDimitry Andric 
61798bcb0991SDimitry Andric     EVT VT = isPPC64 ? MVT::i64 : MVT::i32;
61808bcb0991SDimitry Andric     SDNode *Tmp = CurDAG->getMachineNode(
61818bcb0991SDimitry Andric         isPPC64 ? PPC::ADDIStocHA8 : PPC::ADDIStocHA, dl, VT, TOCbase, GA);
61828bcb0991SDimitry Andric 
6183*0fca6ea1SDimitry Andric     // On AIX, if the symbol has the toc-data attribute it will be defined
6184*0fca6ea1SDimitry Andric     // in the TOC entry, so we use an ADDItocL/ADDItocL8.
6185*0fca6ea1SDimitry Andric     if (isAIXABI && hasTocDataAttr(GA)) {
6186*0fca6ea1SDimitry Andric       ReplaceNode(
6187*0fca6ea1SDimitry Andric           N, CurDAG->getMachineNode(isPPC64 ? PPC::ADDItocL8 : PPC::ADDItocL,
6188*0fca6ea1SDimitry Andric                                     dl, VT, SDValue(Tmp, 0), GA));
6189*0fca6ea1SDimitry Andric       return;
6190*0fca6ea1SDimitry Andric     }
6191*0fca6ea1SDimitry Andric 
61920b57cec5SDimitry Andric     if (PPCLowering->isAccessedAsGotIndirect(GA)) {
61938bcb0991SDimitry Andric       // If it is accessed as got-indirect, we need an extra LWZ/LD to load
61940b57cec5SDimitry Andric       // the address.
61958bcb0991SDimitry Andric       SDNode *MN = CurDAG->getMachineNode(
61968bcb0991SDimitry Andric           isPPC64 ? PPC::LDtocL : PPC::LWZtocL, dl, VT, GA, SDValue(Tmp, 0));
61978bcb0991SDimitry Andric 
61980b57cec5SDimitry Andric       transferMemOperands(N, MN);
61990b57cec5SDimitry Andric       ReplaceNode(N, MN);
62000b57cec5SDimitry Andric       return;
62010b57cec5SDimitry Andric     }
62020b57cec5SDimitry Andric 
6203*0fca6ea1SDimitry Andric     assert(isPPC64 && "TOC_ENTRY already handled for 32-bit.");
62048bcb0991SDimitry Andric     // Build the address relative to the TOC-pointer.
6205*0fca6ea1SDimitry Andric     ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL8, dl, MVT::i64,
62060b57cec5SDimitry Andric                                           SDValue(Tmp, 0), GA));
62070b57cec5SDimitry Andric     return;
62080b57cec5SDimitry Andric   }
62090b57cec5SDimitry Andric   case PPCISD::PPC32_PICGOT:
62100b57cec5SDimitry Andric     // Generate a PIC-safe GOT reference.
62115ffd83dbSDimitry Andric     assert(Subtarget->is32BitELFABI() &&
62120b57cec5SDimitry Andric            "PPCISD::PPC32_PICGOT is only supported for 32-bit SVR4");
62130b57cec5SDimitry Andric     CurDAG->SelectNodeTo(N, PPC::PPC32PICGOT,
62140b57cec5SDimitry Andric                          PPCLowering->getPointerTy(CurDAG->getDataLayout()),
62150b57cec5SDimitry Andric                          MVT::i32);
62160b57cec5SDimitry Andric     return;
62170b57cec5SDimitry Andric 
62180b57cec5SDimitry Andric   case PPCISD::VADD_SPLAT: {
62190b57cec5SDimitry Andric     // This expands into one of three sequences, depending on whether
62200b57cec5SDimitry Andric     // the first operand is odd or even, positive or negative.
62210b57cec5SDimitry Andric     assert(isa<ConstantSDNode>(N->getOperand(0)) &&
62220b57cec5SDimitry Andric            isa<ConstantSDNode>(N->getOperand(1)) &&
62230b57cec5SDimitry Andric            "Invalid operand on VADD_SPLAT!");
62240b57cec5SDimitry Andric 
62250b57cec5SDimitry Andric     int Elt     = N->getConstantOperandVal(0);
62260b57cec5SDimitry Andric     int EltSize = N->getConstantOperandVal(1);
62270b57cec5SDimitry Andric     unsigned Opc1, Opc2, Opc3;
62280b57cec5SDimitry Andric     EVT VT;
62290b57cec5SDimitry Andric 
62300b57cec5SDimitry Andric     if (EltSize == 1) {
62310b57cec5SDimitry Andric       Opc1 = PPC::VSPLTISB;
62320b57cec5SDimitry Andric       Opc2 = PPC::VADDUBM;
62330b57cec5SDimitry Andric       Opc3 = PPC::VSUBUBM;
62340b57cec5SDimitry Andric       VT = MVT::v16i8;
62350b57cec5SDimitry Andric     } else if (EltSize == 2) {
62360b57cec5SDimitry Andric       Opc1 = PPC::VSPLTISH;
62370b57cec5SDimitry Andric       Opc2 = PPC::VADDUHM;
62380b57cec5SDimitry Andric       Opc3 = PPC::VSUBUHM;
62390b57cec5SDimitry Andric       VT = MVT::v8i16;
62400b57cec5SDimitry Andric     } else {
62410b57cec5SDimitry Andric       assert(EltSize == 4 && "Invalid element size on VADD_SPLAT!");
62420b57cec5SDimitry Andric       Opc1 = PPC::VSPLTISW;
62430b57cec5SDimitry Andric       Opc2 = PPC::VADDUWM;
62440b57cec5SDimitry Andric       Opc3 = PPC::VSUBUWM;
62450b57cec5SDimitry Andric       VT = MVT::v4i32;
62460b57cec5SDimitry Andric     }
62470b57cec5SDimitry Andric 
62480b57cec5SDimitry Andric     if ((Elt & 1) == 0) {
62490b57cec5SDimitry Andric       // Elt is even, in the range [-32,-18] + [16,30].
62500b57cec5SDimitry Andric       //
62510b57cec5SDimitry Andric       // Convert: VADD_SPLAT elt, size
62520b57cec5SDimitry Andric       // Into:    tmp = VSPLTIS[BHW] elt
62530b57cec5SDimitry Andric       //          VADDU[BHW]M tmp, tmp
62540b57cec5SDimitry Andric       // Where:   [BHW] = B for size = 1, H for size = 2, W for size = 4
62550b57cec5SDimitry Andric       SDValue EltVal = getI32Imm(Elt >> 1, dl);
62560b57cec5SDimitry Andric       SDNode *Tmp = CurDAG->getMachineNode(Opc1, dl, VT, EltVal);
62570b57cec5SDimitry Andric       SDValue TmpVal = SDValue(Tmp, 0);
62580b57cec5SDimitry Andric       ReplaceNode(N, CurDAG->getMachineNode(Opc2, dl, VT, TmpVal, TmpVal));
62590b57cec5SDimitry Andric       return;
62600b57cec5SDimitry Andric     } else if (Elt > 0) {
62610b57cec5SDimitry Andric       // Elt is odd and positive, in the range [17,31].
62620b57cec5SDimitry Andric       //
62630b57cec5SDimitry Andric       // Convert: VADD_SPLAT elt, size
62640b57cec5SDimitry Andric       // Into:    tmp1 = VSPLTIS[BHW] elt-16
62650b57cec5SDimitry Andric       //          tmp2 = VSPLTIS[BHW] -16
62660b57cec5SDimitry Andric       //          VSUBU[BHW]M tmp1, tmp2
62670b57cec5SDimitry Andric       SDValue EltVal = getI32Imm(Elt - 16, dl);
62680b57cec5SDimitry Andric       SDNode *Tmp1 = CurDAG->getMachineNode(Opc1, dl, VT, EltVal);
62690b57cec5SDimitry Andric       EltVal = getI32Imm(-16, dl);
62700b57cec5SDimitry Andric       SDNode *Tmp2 = CurDAG->getMachineNode(Opc1, dl, VT, EltVal);
62710b57cec5SDimitry Andric       ReplaceNode(N, CurDAG->getMachineNode(Opc3, dl, VT, SDValue(Tmp1, 0),
62720b57cec5SDimitry Andric                                             SDValue(Tmp2, 0)));
62730b57cec5SDimitry Andric       return;
62740b57cec5SDimitry Andric     } else {
62750b57cec5SDimitry Andric       // Elt is odd and negative, in the range [-31,-17].
62760b57cec5SDimitry Andric       //
62770b57cec5SDimitry Andric       // Convert: VADD_SPLAT elt, size
62780b57cec5SDimitry Andric       // Into:    tmp1 = VSPLTIS[BHW] elt+16
62790b57cec5SDimitry Andric       //          tmp2 = VSPLTIS[BHW] -16
62800b57cec5SDimitry Andric       //          VADDU[BHW]M tmp1, tmp2
62810b57cec5SDimitry Andric       SDValue EltVal = getI32Imm(Elt + 16, dl);
62820b57cec5SDimitry Andric       SDNode *Tmp1 = CurDAG->getMachineNode(Opc1, dl, VT, EltVal);
62830b57cec5SDimitry Andric       EltVal = getI32Imm(-16, dl);
62840b57cec5SDimitry Andric       SDNode *Tmp2 = CurDAG->getMachineNode(Opc1, dl, VT, EltVal);
62850b57cec5SDimitry Andric       ReplaceNode(N, CurDAG->getMachineNode(Opc2, dl, VT, SDValue(Tmp1, 0),
62860b57cec5SDimitry Andric                                             SDValue(Tmp2, 0)));
62870b57cec5SDimitry Andric       return;
62880b57cec5SDimitry Andric     }
62890b57cec5SDimitry Andric   }
6290349cc55cSDimitry Andric   case PPCISD::LD_SPLAT: {
6291349cc55cSDimitry Andric     // Here we want to handle splat load for type v16i8 and v8i16 when there is
6292349cc55cSDimitry Andric     // no direct move, we don't need to use stack for this case. If target has
6293349cc55cSDimitry Andric     // direct move, we should be able to get the best selection in the .td file.
6294349cc55cSDimitry Andric     if (!Subtarget->hasAltivec() || Subtarget->hasDirectMove())
6295349cc55cSDimitry Andric       break;
6296349cc55cSDimitry Andric 
6297349cc55cSDimitry Andric     EVT Type = N->getValueType(0);
6298349cc55cSDimitry Andric     if (Type != MVT::v16i8 && Type != MVT::v8i16)
6299349cc55cSDimitry Andric       break;
6300349cc55cSDimitry Andric 
63010eae32dcSDimitry Andric     // If the alignment for the load is 16 or bigger, we don't need the
63020eae32dcSDimitry Andric     // permutated mask to get the required value. The value must be the 0
63030eae32dcSDimitry Andric     // element in big endian target or 7/15 in little endian target in the
63040eae32dcSDimitry Andric     // result vsx register of lvx instruction.
63050eae32dcSDimitry Andric     // Select the instruction in the .td file.
63060eae32dcSDimitry Andric     if (cast<MemIntrinsicSDNode>(N)->getAlign() >= Align(16) &&
63070eae32dcSDimitry Andric         isOffsetMultipleOf(N, 16))
63080eae32dcSDimitry Andric       break;
63090eae32dcSDimitry Andric 
6310349cc55cSDimitry Andric     SDValue ZeroReg =
6311349cc55cSDimitry Andric         CurDAG->getRegister(Subtarget->isPPC64() ? PPC::ZERO8 : PPC::ZERO,
6312349cc55cSDimitry Andric                             Subtarget->isPPC64() ? MVT::i64 : MVT::i32);
6313349cc55cSDimitry Andric     unsigned LIOpcode = Subtarget->isPPC64() ? PPC::LI8 : PPC::LI;
6314349cc55cSDimitry Andric     // v16i8 LD_SPLAT addr
6315349cc55cSDimitry Andric     // ======>
6316349cc55cSDimitry Andric     // Mask = LVSR/LVSL 0, addr
6317349cc55cSDimitry Andric     // LoadLow = LVX 0, addr
6318349cc55cSDimitry Andric     // Perm = VPERM LoadLow, LoadLow, Mask
6319349cc55cSDimitry Andric     // Splat = VSPLTB 15/0, Perm
6320349cc55cSDimitry Andric     //
6321349cc55cSDimitry Andric     // v8i16 LD_SPLAT addr
6322349cc55cSDimitry Andric     // ======>
6323349cc55cSDimitry Andric     // Mask = LVSR/LVSL 0, addr
6324349cc55cSDimitry Andric     // LoadLow = LVX 0, addr
6325349cc55cSDimitry Andric     // LoadHigh = LVX (LI, 1), addr
6326349cc55cSDimitry Andric     // Perm = VPERM LoadLow, LoadHigh, Mask
6327349cc55cSDimitry Andric     // Splat = VSPLTH 7/0, Perm
6328349cc55cSDimitry Andric     unsigned SplatOp = (Type == MVT::v16i8) ? PPC::VSPLTB : PPC::VSPLTH;
6329349cc55cSDimitry Andric     unsigned SplatElemIndex =
6330349cc55cSDimitry Andric         Subtarget->isLittleEndian() ? ((Type == MVT::v16i8) ? 15 : 7) : 0;
6331349cc55cSDimitry Andric 
6332349cc55cSDimitry Andric     SDNode *Mask = CurDAG->getMachineNode(
6333349cc55cSDimitry Andric         Subtarget->isLittleEndian() ? PPC::LVSR : PPC::LVSL, dl, Type, ZeroReg,
6334349cc55cSDimitry Andric         N->getOperand(1));
6335349cc55cSDimitry Andric 
6336349cc55cSDimitry Andric     SDNode *LoadLow =
6337349cc55cSDimitry Andric         CurDAG->getMachineNode(PPC::LVX, dl, MVT::v16i8, MVT::Other,
6338349cc55cSDimitry Andric                                {ZeroReg, N->getOperand(1), N->getOperand(0)});
6339349cc55cSDimitry Andric 
6340349cc55cSDimitry Andric     SDNode *LoadHigh = LoadLow;
6341349cc55cSDimitry Andric     if (Type == MVT::v8i16) {
6342349cc55cSDimitry Andric       LoadHigh = CurDAG->getMachineNode(
6343349cc55cSDimitry Andric           PPC::LVX, dl, MVT::v16i8, MVT::Other,
6344349cc55cSDimitry Andric           {SDValue(CurDAG->getMachineNode(
6345349cc55cSDimitry Andric                        LIOpcode, dl, MVT::i32,
6346349cc55cSDimitry Andric                        CurDAG->getTargetConstant(1, dl, MVT::i8)),
6347349cc55cSDimitry Andric                    0),
6348349cc55cSDimitry Andric            N->getOperand(1), SDValue(LoadLow, 1)});
6349349cc55cSDimitry Andric     }
6350349cc55cSDimitry Andric 
6351349cc55cSDimitry Andric     CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 1), SDValue(LoadHigh, 1));
6352349cc55cSDimitry Andric     transferMemOperands(N, LoadHigh);
6353349cc55cSDimitry Andric 
6354349cc55cSDimitry Andric     SDNode *Perm =
6355349cc55cSDimitry Andric         CurDAG->getMachineNode(PPC::VPERM, dl, Type, SDValue(LoadLow, 0),
6356349cc55cSDimitry Andric                                SDValue(LoadHigh, 0), SDValue(Mask, 0));
6357349cc55cSDimitry Andric     CurDAG->SelectNodeTo(N, SplatOp, Type,
6358349cc55cSDimitry Andric                          CurDAG->getTargetConstant(SplatElemIndex, dl, MVT::i8),
6359349cc55cSDimitry Andric                          SDValue(Perm, 0));
6360349cc55cSDimitry Andric     return;
6361349cc55cSDimitry Andric   }
63620b57cec5SDimitry Andric   }
63630b57cec5SDimitry Andric 
63640b57cec5SDimitry Andric   SelectCode(N);
63650b57cec5SDimitry Andric }
63660b57cec5SDimitry Andric 
63670b57cec5SDimitry Andric // If the target supports the cmpb instruction, do the idiom recognition here.
63680b57cec5SDimitry Andric // We don't do this as a DAG combine because we don't want to do it as nodes
63690b57cec5SDimitry Andric // are being combined (because we might miss part of the eventual idiom). We
63700b57cec5SDimitry Andric // don't want to do it during instruction selection because we want to reuse
63710b57cec5SDimitry Andric // the logic for lowering the masking operations already part of the
63720b57cec5SDimitry Andric // instruction selector.
combineToCMPB(SDNode * N)63730b57cec5SDimitry Andric SDValue PPCDAGToDAGISel::combineToCMPB(SDNode *N) {
63740b57cec5SDimitry Andric   SDLoc dl(N);
63750b57cec5SDimitry Andric 
63760b57cec5SDimitry Andric   assert(N->getOpcode() == ISD::OR &&
63770b57cec5SDimitry Andric          "Only OR nodes are supported for CMPB");
63780b57cec5SDimitry Andric 
63790b57cec5SDimitry Andric   SDValue Res;
63805ffd83dbSDimitry Andric   if (!Subtarget->hasCMPB())
63810b57cec5SDimitry Andric     return Res;
63820b57cec5SDimitry Andric 
63830b57cec5SDimitry Andric   if (N->getValueType(0) != MVT::i32 &&
63840b57cec5SDimitry Andric       N->getValueType(0) != MVT::i64)
63850b57cec5SDimitry Andric     return Res;
63860b57cec5SDimitry Andric 
63870b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
63880b57cec5SDimitry Andric 
63890b57cec5SDimitry Andric   SDValue RHS, LHS;
63900b57cec5SDimitry Andric   bool BytesFound[8] = {false, false, false, false, false, false, false, false};
63910b57cec5SDimitry Andric   uint64_t Mask = 0, Alt = 0;
63920b57cec5SDimitry Andric 
63930b57cec5SDimitry Andric   auto IsByteSelectCC = [this](SDValue O, unsigned &b,
63940b57cec5SDimitry Andric                                uint64_t &Mask, uint64_t &Alt,
63950b57cec5SDimitry Andric                                SDValue &LHS, SDValue &RHS) {
63960b57cec5SDimitry Andric     if (O.getOpcode() != ISD::SELECT_CC)
63970b57cec5SDimitry Andric       return false;
63980b57cec5SDimitry Andric     ISD::CondCode CC = cast<CondCodeSDNode>(O.getOperand(4))->get();
63990b57cec5SDimitry Andric 
64000b57cec5SDimitry Andric     if (!isa<ConstantSDNode>(O.getOperand(2)) ||
64010b57cec5SDimitry Andric         !isa<ConstantSDNode>(O.getOperand(3)))
64020b57cec5SDimitry Andric       return false;
64030b57cec5SDimitry Andric 
64040b57cec5SDimitry Andric     uint64_t PM = O.getConstantOperandVal(2);
64050b57cec5SDimitry Andric     uint64_t PAlt = O.getConstantOperandVal(3);
64060b57cec5SDimitry Andric     for (b = 0; b < 8; ++b) {
64070b57cec5SDimitry Andric       uint64_t Mask = UINT64_C(0xFF) << (8*b);
64080b57cec5SDimitry Andric       if (PM && (PM & Mask) == PM && (PAlt & Mask) == PAlt)
64090b57cec5SDimitry Andric         break;
64100b57cec5SDimitry Andric     }
64110b57cec5SDimitry Andric 
64120b57cec5SDimitry Andric     if (b == 8)
64130b57cec5SDimitry Andric       return false;
64140b57cec5SDimitry Andric     Mask |= PM;
64150b57cec5SDimitry Andric     Alt  |= PAlt;
64160b57cec5SDimitry Andric 
64170b57cec5SDimitry Andric     if (!isa<ConstantSDNode>(O.getOperand(1)) ||
64180b57cec5SDimitry Andric         O.getConstantOperandVal(1) != 0) {
64190b57cec5SDimitry Andric       SDValue Op0 = O.getOperand(0), Op1 = O.getOperand(1);
64200b57cec5SDimitry Andric       if (Op0.getOpcode() == ISD::TRUNCATE)
64210b57cec5SDimitry Andric         Op0 = Op0.getOperand(0);
64220b57cec5SDimitry Andric       if (Op1.getOpcode() == ISD::TRUNCATE)
64230b57cec5SDimitry Andric         Op1 = Op1.getOperand(0);
64240b57cec5SDimitry Andric 
64250b57cec5SDimitry Andric       if (Op0.getOpcode() == ISD::SRL && Op1.getOpcode() == ISD::SRL &&
64260b57cec5SDimitry Andric           Op0.getOperand(1) == Op1.getOperand(1) && CC == ISD::SETEQ &&
64270b57cec5SDimitry Andric           isa<ConstantSDNode>(Op0.getOperand(1))) {
64280b57cec5SDimitry Andric 
64290b57cec5SDimitry Andric         unsigned Bits = Op0.getValueSizeInBits();
64300b57cec5SDimitry Andric         if (b != Bits/8-1)
64310b57cec5SDimitry Andric           return false;
64320b57cec5SDimitry Andric         if (Op0.getConstantOperandVal(1) != Bits-8)
64330b57cec5SDimitry Andric           return false;
64340b57cec5SDimitry Andric 
64350b57cec5SDimitry Andric         LHS = Op0.getOperand(0);
64360b57cec5SDimitry Andric         RHS = Op1.getOperand(0);
64370b57cec5SDimitry Andric         return true;
64380b57cec5SDimitry Andric       }
64390b57cec5SDimitry Andric 
64400b57cec5SDimitry Andric       // When we have small integers (i16 to be specific), the form present
64410b57cec5SDimitry Andric       // post-legalization uses SETULT in the SELECT_CC for the
64420b57cec5SDimitry Andric       // higher-order byte, depending on the fact that the
64430b57cec5SDimitry Andric       // even-higher-order bytes are known to all be zero, for example:
64440b57cec5SDimitry Andric       //   select_cc (xor $lhs, $rhs), 256, 65280, 0, setult
64450b57cec5SDimitry Andric       // (so when the second byte is the same, because all higher-order
64460b57cec5SDimitry Andric       // bits from bytes 3 and 4 are known to be zero, the result of the
64470b57cec5SDimitry Andric       // xor can be at most 255)
64480b57cec5SDimitry Andric       if (Op0.getOpcode() == ISD::XOR && CC == ISD::SETULT &&
64490b57cec5SDimitry Andric           isa<ConstantSDNode>(O.getOperand(1))) {
64500b57cec5SDimitry Andric 
64510b57cec5SDimitry Andric         uint64_t ULim = O.getConstantOperandVal(1);
64520b57cec5SDimitry Andric         if (ULim != (UINT64_C(1) << b*8))
64530b57cec5SDimitry Andric           return false;
64540b57cec5SDimitry Andric 
64550b57cec5SDimitry Andric         // Now we need to make sure that the upper bytes are known to be
64560b57cec5SDimitry Andric         // zero.
64570b57cec5SDimitry Andric         unsigned Bits = Op0.getValueSizeInBits();
64580b57cec5SDimitry Andric         if (!CurDAG->MaskedValueIsZero(
64590b57cec5SDimitry Andric                 Op0, APInt::getHighBitsSet(Bits, Bits - (b + 1) * 8)))
64600b57cec5SDimitry Andric           return false;
64610b57cec5SDimitry Andric 
64620b57cec5SDimitry Andric         LHS = Op0.getOperand(0);
64630b57cec5SDimitry Andric         RHS = Op0.getOperand(1);
64640b57cec5SDimitry Andric         return true;
64650b57cec5SDimitry Andric       }
64660b57cec5SDimitry Andric 
64670b57cec5SDimitry Andric       return false;
64680b57cec5SDimitry Andric     }
64690b57cec5SDimitry Andric 
64700b57cec5SDimitry Andric     if (CC != ISD::SETEQ)
64710b57cec5SDimitry Andric       return false;
64720b57cec5SDimitry Andric 
64730b57cec5SDimitry Andric     SDValue Op = O.getOperand(0);
64740b57cec5SDimitry Andric     if (Op.getOpcode() == ISD::AND) {
64750b57cec5SDimitry Andric       if (!isa<ConstantSDNode>(Op.getOperand(1)))
64760b57cec5SDimitry Andric         return false;
64770b57cec5SDimitry Andric       if (Op.getConstantOperandVal(1) != (UINT64_C(0xFF) << (8*b)))
64780b57cec5SDimitry Andric         return false;
64790b57cec5SDimitry Andric 
64800b57cec5SDimitry Andric       SDValue XOR = Op.getOperand(0);
64810b57cec5SDimitry Andric       if (XOR.getOpcode() == ISD::TRUNCATE)
64820b57cec5SDimitry Andric         XOR = XOR.getOperand(0);
64830b57cec5SDimitry Andric       if (XOR.getOpcode() != ISD::XOR)
64840b57cec5SDimitry Andric         return false;
64850b57cec5SDimitry Andric 
64860b57cec5SDimitry Andric       LHS = XOR.getOperand(0);
64870b57cec5SDimitry Andric       RHS = XOR.getOperand(1);
64880b57cec5SDimitry Andric       return true;
64890b57cec5SDimitry Andric     } else if (Op.getOpcode() == ISD::SRL) {
64900b57cec5SDimitry Andric       if (!isa<ConstantSDNode>(Op.getOperand(1)))
64910b57cec5SDimitry Andric         return false;
64920b57cec5SDimitry Andric       unsigned Bits = Op.getValueSizeInBits();
64930b57cec5SDimitry Andric       if (b != Bits/8-1)
64940b57cec5SDimitry Andric         return false;
64950b57cec5SDimitry Andric       if (Op.getConstantOperandVal(1) != Bits-8)
64960b57cec5SDimitry Andric         return false;
64970b57cec5SDimitry Andric 
64980b57cec5SDimitry Andric       SDValue XOR = Op.getOperand(0);
64990b57cec5SDimitry Andric       if (XOR.getOpcode() == ISD::TRUNCATE)
65000b57cec5SDimitry Andric         XOR = XOR.getOperand(0);
65010b57cec5SDimitry Andric       if (XOR.getOpcode() != ISD::XOR)
65020b57cec5SDimitry Andric         return false;
65030b57cec5SDimitry Andric 
65040b57cec5SDimitry Andric       LHS = XOR.getOperand(0);
65050b57cec5SDimitry Andric       RHS = XOR.getOperand(1);
65060b57cec5SDimitry Andric       return true;
65070b57cec5SDimitry Andric     }
65080b57cec5SDimitry Andric 
65090b57cec5SDimitry Andric     return false;
65100b57cec5SDimitry Andric   };
65110b57cec5SDimitry Andric 
65120b57cec5SDimitry Andric   SmallVector<SDValue, 8> Queue(1, SDValue(N, 0));
65130b57cec5SDimitry Andric   while (!Queue.empty()) {
65140b57cec5SDimitry Andric     SDValue V = Queue.pop_back_val();
65150b57cec5SDimitry Andric 
65160b57cec5SDimitry Andric     for (const SDValue &O : V.getNode()->ops()) {
65170b57cec5SDimitry Andric       unsigned b = 0;
65180b57cec5SDimitry Andric       uint64_t M = 0, A = 0;
65190b57cec5SDimitry Andric       SDValue OLHS, ORHS;
65200b57cec5SDimitry Andric       if (O.getOpcode() == ISD::OR) {
65210b57cec5SDimitry Andric         Queue.push_back(O);
65220b57cec5SDimitry Andric       } else if (IsByteSelectCC(O, b, M, A, OLHS, ORHS)) {
65230b57cec5SDimitry Andric         if (!LHS) {
65240b57cec5SDimitry Andric           LHS = OLHS;
65250b57cec5SDimitry Andric           RHS = ORHS;
65260b57cec5SDimitry Andric           BytesFound[b] = true;
65270b57cec5SDimitry Andric           Mask |= M;
65280b57cec5SDimitry Andric           Alt  |= A;
65290b57cec5SDimitry Andric         } else if ((LHS == ORHS && RHS == OLHS) ||
65300b57cec5SDimitry Andric                    (RHS == ORHS && LHS == OLHS)) {
65310b57cec5SDimitry Andric           BytesFound[b] = true;
65320b57cec5SDimitry Andric           Mask |= M;
65330b57cec5SDimitry Andric           Alt  |= A;
65340b57cec5SDimitry Andric         } else {
65350b57cec5SDimitry Andric           return Res;
65360b57cec5SDimitry Andric         }
65370b57cec5SDimitry Andric       } else {
65380b57cec5SDimitry Andric         return Res;
65390b57cec5SDimitry Andric       }
65400b57cec5SDimitry Andric     }
65410b57cec5SDimitry Andric   }
65420b57cec5SDimitry Andric 
65430b57cec5SDimitry Andric   unsigned LastB = 0, BCnt = 0;
65440b57cec5SDimitry Andric   for (unsigned i = 0; i < 8; ++i)
65450b57cec5SDimitry Andric     if (BytesFound[LastB]) {
65460b57cec5SDimitry Andric       ++BCnt;
65470b57cec5SDimitry Andric       LastB = i;
65480b57cec5SDimitry Andric     }
65490b57cec5SDimitry Andric 
65500b57cec5SDimitry Andric   if (!LastB || BCnt < 2)
65510b57cec5SDimitry Andric     return Res;
65520b57cec5SDimitry Andric 
65530b57cec5SDimitry Andric   // Because we'll be zero-extending the output anyway if don't have a specific
65540b57cec5SDimitry Andric   // value for each input byte (via the Mask), we can 'anyext' the inputs.
65550b57cec5SDimitry Andric   if (LHS.getValueType() != VT) {
65560b57cec5SDimitry Andric     LHS = CurDAG->getAnyExtOrTrunc(LHS, dl, VT);
65570b57cec5SDimitry Andric     RHS = CurDAG->getAnyExtOrTrunc(RHS, dl, VT);
65580b57cec5SDimitry Andric   }
65590b57cec5SDimitry Andric 
65600b57cec5SDimitry Andric   Res = CurDAG->getNode(PPCISD::CMPB, dl, VT, LHS, RHS);
65610b57cec5SDimitry Andric 
65620b57cec5SDimitry Andric   bool NonTrivialMask = ((int64_t) Mask) != INT64_C(-1);
65630b57cec5SDimitry Andric   if (NonTrivialMask && !Alt) {
65640b57cec5SDimitry Andric     // Res = Mask & CMPB
65650b57cec5SDimitry Andric     Res = CurDAG->getNode(ISD::AND, dl, VT, Res,
65660b57cec5SDimitry Andric                           CurDAG->getConstant(Mask, dl, VT));
65670b57cec5SDimitry Andric   } else if (Alt) {
65680b57cec5SDimitry Andric     // Res = (CMPB & Mask) | (~CMPB & Alt)
65690b57cec5SDimitry Andric     // Which, as suggested here:
65700b57cec5SDimitry Andric     //   https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
65710b57cec5SDimitry Andric     // can be written as:
65720b57cec5SDimitry Andric     // Res = Alt ^ ((Alt ^ Mask) & CMPB)
65730b57cec5SDimitry Andric     // useful because the (Alt ^ Mask) can be pre-computed.
65740b57cec5SDimitry Andric     Res = CurDAG->getNode(ISD::AND, dl, VT, Res,
65750b57cec5SDimitry Andric                           CurDAG->getConstant(Mask ^ Alt, dl, VT));
65760b57cec5SDimitry Andric     Res = CurDAG->getNode(ISD::XOR, dl, VT, Res,
65770b57cec5SDimitry Andric                           CurDAG->getConstant(Alt, dl, VT));
65780b57cec5SDimitry Andric   }
65790b57cec5SDimitry Andric 
65800b57cec5SDimitry Andric   return Res;
65810b57cec5SDimitry Andric }
65820b57cec5SDimitry Andric 
65830b57cec5SDimitry Andric // When CR bit registers are enabled, an extension of an i1 variable to a i32
65840b57cec5SDimitry Andric // or i64 value is lowered in terms of a SELECT_I[48] operation, and thus
65850b57cec5SDimitry Andric // involves constant materialization of a 0 or a 1 or both. If the result of
65860b57cec5SDimitry Andric // the extension is then operated upon by some operator that can be constant
65870b57cec5SDimitry Andric // folded with a constant 0 or 1, and that constant can be materialized using
65880b57cec5SDimitry Andric // only one instruction (like a zero or one), then we should fold in those
65890b57cec5SDimitry Andric // operations with the select.
foldBoolExts(SDValue & Res,SDNode * & N)65900b57cec5SDimitry Andric void PPCDAGToDAGISel::foldBoolExts(SDValue &Res, SDNode *&N) {
65915ffd83dbSDimitry Andric   if (!Subtarget->useCRBits())
65920b57cec5SDimitry Andric     return;
65930b57cec5SDimitry Andric 
65940b57cec5SDimitry Andric   if (N->getOpcode() != ISD::ZERO_EXTEND &&
65950b57cec5SDimitry Andric       N->getOpcode() != ISD::SIGN_EXTEND &&
65960b57cec5SDimitry Andric       N->getOpcode() != ISD::ANY_EXTEND)
65970b57cec5SDimitry Andric     return;
65980b57cec5SDimitry Andric 
65990b57cec5SDimitry Andric   if (N->getOperand(0).getValueType() != MVT::i1)
66000b57cec5SDimitry Andric     return;
66010b57cec5SDimitry Andric 
66020b57cec5SDimitry Andric   if (!N->hasOneUse())
66030b57cec5SDimitry Andric     return;
66040b57cec5SDimitry Andric 
66050b57cec5SDimitry Andric   SDLoc dl(N);
66060b57cec5SDimitry Andric   EVT VT = N->getValueType(0);
66070b57cec5SDimitry Andric   SDValue Cond = N->getOperand(0);
66080b57cec5SDimitry Andric   SDValue ConstTrue =
66090b57cec5SDimitry Andric     CurDAG->getConstant(N->getOpcode() == ISD::SIGN_EXTEND ? -1 : 1, dl, VT);
66100b57cec5SDimitry Andric   SDValue ConstFalse = CurDAG->getConstant(0, dl, VT);
66110b57cec5SDimitry Andric 
66120b57cec5SDimitry Andric   do {
66130b57cec5SDimitry Andric     SDNode *User = *N->use_begin();
66140b57cec5SDimitry Andric     if (User->getNumOperands() != 2)
66150b57cec5SDimitry Andric       break;
66160b57cec5SDimitry Andric 
66170b57cec5SDimitry Andric     auto TryFold = [this, N, User, dl](SDValue Val) {
66180b57cec5SDimitry Andric       SDValue UserO0 = User->getOperand(0), UserO1 = User->getOperand(1);
66190b57cec5SDimitry Andric       SDValue O0 = UserO0.getNode() == N ? Val : UserO0;
66200b57cec5SDimitry Andric       SDValue O1 = UserO1.getNode() == N ? Val : UserO1;
66210b57cec5SDimitry Andric 
66220b57cec5SDimitry Andric       return CurDAG->FoldConstantArithmetic(User->getOpcode(), dl,
66235ffd83dbSDimitry Andric                                             User->getValueType(0), {O0, O1});
66240b57cec5SDimitry Andric     };
66250b57cec5SDimitry Andric 
66260b57cec5SDimitry Andric     // FIXME: When the semantics of the interaction between select and undef
66270b57cec5SDimitry Andric     // are clearly defined, it may turn out to be unnecessary to break here.
66280b57cec5SDimitry Andric     SDValue TrueRes = TryFold(ConstTrue);
66290b57cec5SDimitry Andric     if (!TrueRes || TrueRes.isUndef())
66300b57cec5SDimitry Andric       break;
66310b57cec5SDimitry Andric     SDValue FalseRes = TryFold(ConstFalse);
66320b57cec5SDimitry Andric     if (!FalseRes || FalseRes.isUndef())
66330b57cec5SDimitry Andric       break;
66340b57cec5SDimitry Andric 
66350b57cec5SDimitry Andric     // For us to materialize these using one instruction, we must be able to
66360b57cec5SDimitry Andric     // represent them as signed 16-bit integers.
66371db9f3b2SDimitry Andric     uint64_t True = TrueRes->getAsZExtVal(), False = FalseRes->getAsZExtVal();
66380b57cec5SDimitry Andric     if (!isInt<16>(True) || !isInt<16>(False))
66390b57cec5SDimitry Andric       break;
66400b57cec5SDimitry Andric 
66410b57cec5SDimitry Andric     // We can replace User with a new SELECT node, and try again to see if we
66420b57cec5SDimitry Andric     // can fold the select with its user.
66430b57cec5SDimitry Andric     Res = CurDAG->getSelect(dl, User->getValueType(0), Cond, TrueRes, FalseRes);
66440b57cec5SDimitry Andric     N = User;
66450b57cec5SDimitry Andric     ConstTrue = TrueRes;
66460b57cec5SDimitry Andric     ConstFalse = FalseRes;
66470b57cec5SDimitry Andric   } while (N->hasOneUse());
66480b57cec5SDimitry Andric }
66490b57cec5SDimitry Andric 
PreprocessISelDAG()66500b57cec5SDimitry Andric void PPCDAGToDAGISel::PreprocessISelDAG() {
66510b57cec5SDimitry Andric   SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
66520b57cec5SDimitry Andric 
66530b57cec5SDimitry Andric   bool MadeChange = false;
66540b57cec5SDimitry Andric   while (Position != CurDAG->allnodes_begin()) {
66550b57cec5SDimitry Andric     SDNode *N = &*--Position;
66560b57cec5SDimitry Andric     if (N->use_empty())
66570b57cec5SDimitry Andric       continue;
66580b57cec5SDimitry Andric 
66590b57cec5SDimitry Andric     SDValue Res;
66600b57cec5SDimitry Andric     switch (N->getOpcode()) {
66610b57cec5SDimitry Andric     default: break;
66620b57cec5SDimitry Andric     case ISD::OR:
66630b57cec5SDimitry Andric       Res = combineToCMPB(N);
66640b57cec5SDimitry Andric       break;
66650b57cec5SDimitry Andric     }
66660b57cec5SDimitry Andric 
66670b57cec5SDimitry Andric     if (!Res)
66680b57cec5SDimitry Andric       foldBoolExts(Res, N);
66690b57cec5SDimitry Andric 
66700b57cec5SDimitry Andric     if (Res) {
66710b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "PPC DAG preprocessing replacing:\nOld:    ");
66720b57cec5SDimitry Andric       LLVM_DEBUG(N->dump(CurDAG));
66730b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\nNew: ");
66740b57cec5SDimitry Andric       LLVM_DEBUG(Res.getNode()->dump(CurDAG));
66750b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\n");
66760b57cec5SDimitry Andric 
66770b57cec5SDimitry Andric       CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Res);
66780b57cec5SDimitry Andric       MadeChange = true;
66790b57cec5SDimitry Andric     }
66800b57cec5SDimitry Andric   }
66810b57cec5SDimitry Andric 
66820b57cec5SDimitry Andric   if (MadeChange)
66830b57cec5SDimitry Andric     CurDAG->RemoveDeadNodes();
66840b57cec5SDimitry Andric }
66850b57cec5SDimitry Andric 
66860b57cec5SDimitry Andric /// PostprocessISelDAG - Perform some late peephole optimizations
66870b57cec5SDimitry Andric /// on the DAG representation.
PostprocessISelDAG()66880b57cec5SDimitry Andric void PPCDAGToDAGISel::PostprocessISelDAG() {
66890b57cec5SDimitry Andric   // Skip peepholes at -O0.
66905f757f3fSDimitry Andric   if (TM.getOptLevel() == CodeGenOptLevel::None)
66910b57cec5SDimitry Andric     return;
66920b57cec5SDimitry Andric 
66930b57cec5SDimitry Andric   PeepholePPC64();
66940b57cec5SDimitry Andric   PeepholeCROps();
66950b57cec5SDimitry Andric   PeepholePPC64ZExt();
66960b57cec5SDimitry Andric }
66970b57cec5SDimitry Andric 
66980b57cec5SDimitry Andric // Check if all users of this node will become isel where the second operand
66990b57cec5SDimitry Andric // is the constant zero. If this is so, and if we can negate the condition,
67000b57cec5SDimitry Andric // then we can flip the true and false operands. This will allow the zero to
67010b57cec5SDimitry Andric // be folded with the isel so that we don't need to materialize a register
67020b57cec5SDimitry Andric // containing zero.
AllUsersSelectZero(SDNode * N)67030b57cec5SDimitry Andric bool PPCDAGToDAGISel::AllUsersSelectZero(SDNode *N) {
6704349cc55cSDimitry Andric   for (const SDNode *User : N->uses()) {
67050b57cec5SDimitry Andric     if (!User->isMachineOpcode())
67060b57cec5SDimitry Andric       return false;
67070b57cec5SDimitry Andric     if (User->getMachineOpcode() != PPC::SELECT_I4 &&
67080b57cec5SDimitry Andric         User->getMachineOpcode() != PPC::SELECT_I8)
67090b57cec5SDimitry Andric       return false;
67100b57cec5SDimitry Andric 
6711d409305fSDimitry Andric     SDNode *Op1 = User->getOperand(1).getNode();
67120b57cec5SDimitry Andric     SDNode *Op2 = User->getOperand(2).getNode();
6713d409305fSDimitry Andric     // If we have a degenerate select with two equal operands, swapping will
6714d409305fSDimitry Andric     // not do anything, and we may run into an infinite loop.
6715d409305fSDimitry Andric     if (Op1 == Op2)
6716d409305fSDimitry Andric       return false;
6717d409305fSDimitry Andric 
67180b57cec5SDimitry Andric     if (!Op2->isMachineOpcode())
67190b57cec5SDimitry Andric       return false;
67200b57cec5SDimitry Andric 
67210b57cec5SDimitry Andric     if (Op2->getMachineOpcode() != PPC::LI &&
67220b57cec5SDimitry Andric         Op2->getMachineOpcode() != PPC::LI8)
67230b57cec5SDimitry Andric       return false;
67240b57cec5SDimitry Andric 
67255f757f3fSDimitry Andric     if (!isNullConstant(Op2->getOperand(0)))
67260b57cec5SDimitry Andric       return false;
67270b57cec5SDimitry Andric   }
67280b57cec5SDimitry Andric 
67290b57cec5SDimitry Andric   return true;
67300b57cec5SDimitry Andric }
67310b57cec5SDimitry Andric 
SwapAllSelectUsers(SDNode * N)67320b57cec5SDimitry Andric void PPCDAGToDAGISel::SwapAllSelectUsers(SDNode *N) {
67330b57cec5SDimitry Andric   SmallVector<SDNode *, 4> ToReplace;
6734349cc55cSDimitry Andric   for (SDNode *User : N->uses()) {
67350b57cec5SDimitry Andric     assert((User->getMachineOpcode() == PPC::SELECT_I4 ||
67360b57cec5SDimitry Andric             User->getMachineOpcode() == PPC::SELECT_I8) &&
67370b57cec5SDimitry Andric            "Must have all select users");
67380b57cec5SDimitry Andric     ToReplace.push_back(User);
67390b57cec5SDimitry Andric   }
67400b57cec5SDimitry Andric 
6741349cc55cSDimitry Andric   for (SDNode *User : ToReplace) {
67420b57cec5SDimitry Andric     SDNode *ResNode =
67430b57cec5SDimitry Andric       CurDAG->getMachineNode(User->getMachineOpcode(), SDLoc(User),
67440b57cec5SDimitry Andric                              User->getValueType(0), User->getOperand(0),
67450b57cec5SDimitry Andric                              User->getOperand(2),
67460b57cec5SDimitry Andric                              User->getOperand(1));
67470b57cec5SDimitry Andric 
67480b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "CR Peephole replacing:\nOld:    ");
67490b57cec5SDimitry Andric     LLVM_DEBUG(User->dump(CurDAG));
67500b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\nNew: ");
67510b57cec5SDimitry Andric     LLVM_DEBUG(ResNode->dump(CurDAG));
67520b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n");
67530b57cec5SDimitry Andric 
67540b57cec5SDimitry Andric     ReplaceUses(User, ResNode);
67550b57cec5SDimitry Andric   }
67560b57cec5SDimitry Andric }
67570b57cec5SDimitry Andric 
PeepholeCROps()67580b57cec5SDimitry Andric void PPCDAGToDAGISel::PeepholeCROps() {
67590b57cec5SDimitry Andric   bool IsModified;
67600b57cec5SDimitry Andric   do {
67610b57cec5SDimitry Andric     IsModified = false;
67620b57cec5SDimitry Andric     for (SDNode &Node : CurDAG->allnodes()) {
67630b57cec5SDimitry Andric       MachineSDNode *MachineNode = dyn_cast<MachineSDNode>(&Node);
67640b57cec5SDimitry Andric       if (!MachineNode || MachineNode->use_empty())
67650b57cec5SDimitry Andric         continue;
67660b57cec5SDimitry Andric       SDNode *ResNode = MachineNode;
67670b57cec5SDimitry Andric 
67680b57cec5SDimitry Andric       bool Op1Set   = false, Op1Unset = false,
67690b57cec5SDimitry Andric            Op1Not   = false,
67700b57cec5SDimitry Andric            Op2Set   = false, Op2Unset = false,
67710b57cec5SDimitry Andric            Op2Not   = false;
67720b57cec5SDimitry Andric 
67730b57cec5SDimitry Andric       unsigned Opcode = MachineNode->getMachineOpcode();
67740b57cec5SDimitry Andric       switch (Opcode) {
67750b57cec5SDimitry Andric       default: break;
67760b57cec5SDimitry Andric       case PPC::CRAND:
67770b57cec5SDimitry Andric       case PPC::CRNAND:
67780b57cec5SDimitry Andric       case PPC::CROR:
67790b57cec5SDimitry Andric       case PPC::CRXOR:
67800b57cec5SDimitry Andric       case PPC::CRNOR:
67810b57cec5SDimitry Andric       case PPC::CREQV:
67820b57cec5SDimitry Andric       case PPC::CRANDC:
67830b57cec5SDimitry Andric       case PPC::CRORC: {
67840b57cec5SDimitry Andric         SDValue Op = MachineNode->getOperand(1);
67850b57cec5SDimitry Andric         if (Op.isMachineOpcode()) {
67860b57cec5SDimitry Andric           if (Op.getMachineOpcode() == PPC::CRSET)
67870b57cec5SDimitry Andric             Op2Set = true;
67880b57cec5SDimitry Andric           else if (Op.getMachineOpcode() == PPC::CRUNSET)
67890b57cec5SDimitry Andric             Op2Unset = true;
6790bdd1243dSDimitry Andric           else if ((Op.getMachineOpcode() == PPC::CRNOR &&
6791bdd1243dSDimitry Andric                     Op.getOperand(0) == Op.getOperand(1)) ||
6792bdd1243dSDimitry Andric                    Op.getMachineOpcode() == PPC::CRNOT)
67930b57cec5SDimitry Andric             Op2Not = true;
67940b57cec5SDimitry Andric         }
6795bdd1243dSDimitry Andric         [[fallthrough]];
67960b57cec5SDimitry Andric       }
67970b57cec5SDimitry Andric       case PPC::BC:
67980b57cec5SDimitry Andric       case PPC::BCn:
67990b57cec5SDimitry Andric       case PPC::SELECT_I4:
68000b57cec5SDimitry Andric       case PPC::SELECT_I8:
68010b57cec5SDimitry Andric       case PPC::SELECT_F4:
68020b57cec5SDimitry Andric       case PPC::SELECT_F8:
68030b57cec5SDimitry Andric       case PPC::SELECT_SPE:
68040b57cec5SDimitry Andric       case PPC::SELECT_SPE4:
68050b57cec5SDimitry Andric       case PPC::SELECT_VRRC:
68060b57cec5SDimitry Andric       case PPC::SELECT_VSFRC:
68070b57cec5SDimitry Andric       case PPC::SELECT_VSSRC:
68080b57cec5SDimitry Andric       case PPC::SELECT_VSRC: {
68090b57cec5SDimitry Andric         SDValue Op = MachineNode->getOperand(0);
68100b57cec5SDimitry Andric         if (Op.isMachineOpcode()) {
68110b57cec5SDimitry Andric           if (Op.getMachineOpcode() == PPC::CRSET)
68120b57cec5SDimitry Andric             Op1Set = true;
68130b57cec5SDimitry Andric           else if (Op.getMachineOpcode() == PPC::CRUNSET)
68140b57cec5SDimitry Andric             Op1Unset = true;
6815bdd1243dSDimitry Andric           else if ((Op.getMachineOpcode() == PPC::CRNOR &&
6816bdd1243dSDimitry Andric                     Op.getOperand(0) == Op.getOperand(1)) ||
6817bdd1243dSDimitry Andric                    Op.getMachineOpcode() == PPC::CRNOT)
68180b57cec5SDimitry Andric             Op1Not = true;
68190b57cec5SDimitry Andric         }
68200b57cec5SDimitry Andric         }
68210b57cec5SDimitry Andric         break;
68220b57cec5SDimitry Andric       }
68230b57cec5SDimitry Andric 
68240b57cec5SDimitry Andric       bool SelectSwap = false;
68250b57cec5SDimitry Andric       switch (Opcode) {
68260b57cec5SDimitry Andric       default: break;
68270b57cec5SDimitry Andric       case PPC::CRAND:
68280b57cec5SDimitry Andric         if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
68290b57cec5SDimitry Andric           // x & x = x
68300b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
68310b57cec5SDimitry Andric         else if (Op1Set)
68320b57cec5SDimitry Andric           // 1 & y = y
68330b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(1).getNode();
68340b57cec5SDimitry Andric         else if (Op2Set)
68350b57cec5SDimitry Andric           // x & 1 = x
68360b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
68370b57cec5SDimitry Andric         else if (Op1Unset || Op2Unset)
68380b57cec5SDimitry Andric           // x & 0 = 0 & y = 0
68390b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRUNSET, SDLoc(MachineNode),
68400b57cec5SDimitry Andric                                            MVT::i1);
68410b57cec5SDimitry Andric         else if (Op1Not)
68420b57cec5SDimitry Andric           // ~x & y = andc(y, x)
68430b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRANDC, SDLoc(MachineNode),
68440b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
68450b57cec5SDimitry Andric                                            MachineNode->getOperand(0).
68460b57cec5SDimitry Andric                                              getOperand(0));
68470b57cec5SDimitry Andric         else if (Op2Not)
68480b57cec5SDimitry Andric           // x & ~y = andc(x, y)
68490b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRANDC, SDLoc(MachineNode),
68500b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
68510b57cec5SDimitry Andric                                            MachineNode->getOperand(1).
68520b57cec5SDimitry Andric                                              getOperand(0));
68530b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
68540b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNAND, SDLoc(MachineNode),
68550b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
68560b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
68570b57cec5SDimitry Andric           SelectSwap = true;
68580b57cec5SDimitry Andric         }
68590b57cec5SDimitry Andric         break;
68600b57cec5SDimitry Andric       case PPC::CRNAND:
68610b57cec5SDimitry Andric         if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
68620b57cec5SDimitry Andric           // nand(x, x) -> nor(x, x)
68630b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
68640b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
68650b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
68660b57cec5SDimitry Andric         else if (Op1Set)
68670b57cec5SDimitry Andric           // nand(1, y) -> nor(y, y)
68680b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
68690b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
68700b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
68710b57cec5SDimitry Andric         else if (Op2Set)
68720b57cec5SDimitry Andric           // nand(x, 1) -> nor(x, x)
68730b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
68740b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
68750b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
68760b57cec5SDimitry Andric         else if (Op1Unset || Op2Unset)
68770b57cec5SDimitry Andric           // nand(x, 0) = nand(0, y) = 1
68780b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRSET, SDLoc(MachineNode),
68790b57cec5SDimitry Andric                                            MVT::i1);
68800b57cec5SDimitry Andric         else if (Op1Not)
68810b57cec5SDimitry Andric           // nand(~x, y) = ~(~x & y) = x | ~y = orc(x, y)
68820b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRORC, SDLoc(MachineNode),
68830b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0).
68840b57cec5SDimitry Andric                                                       getOperand(0),
68850b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
68860b57cec5SDimitry Andric         else if (Op2Not)
68870b57cec5SDimitry Andric           // nand(x, ~y) = ~x | y = orc(y, x)
68880b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRORC, SDLoc(MachineNode),
68890b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1).
68900b57cec5SDimitry Andric                                                       getOperand(0),
68910b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
68920b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
68930b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRAND, SDLoc(MachineNode),
68940b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
68950b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
68960b57cec5SDimitry Andric           SelectSwap = true;
68970b57cec5SDimitry Andric         }
68980b57cec5SDimitry Andric         break;
68990b57cec5SDimitry Andric       case PPC::CROR:
69000b57cec5SDimitry Andric         if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
69010b57cec5SDimitry Andric           // x | x = x
69020b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
69030b57cec5SDimitry Andric         else if (Op1Set || Op2Set)
69040b57cec5SDimitry Andric           // x | 1 = 1 | y = 1
69050b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRSET, SDLoc(MachineNode),
69060b57cec5SDimitry Andric                                            MVT::i1);
69070b57cec5SDimitry Andric         else if (Op1Unset)
69080b57cec5SDimitry Andric           // 0 | y = y
69090b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(1).getNode();
69100b57cec5SDimitry Andric         else if (Op2Unset)
69110b57cec5SDimitry Andric           // x | 0 = x
69120b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
69130b57cec5SDimitry Andric         else if (Op1Not)
69140b57cec5SDimitry Andric           // ~x | y = orc(y, x)
69150b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRORC, SDLoc(MachineNode),
69160b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
69170b57cec5SDimitry Andric                                            MachineNode->getOperand(0).
69180b57cec5SDimitry Andric                                              getOperand(0));
69190b57cec5SDimitry Andric         else if (Op2Not)
69200b57cec5SDimitry Andric           // x | ~y = orc(x, y)
69210b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRORC, SDLoc(MachineNode),
69220b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
69230b57cec5SDimitry Andric                                            MachineNode->getOperand(1).
69240b57cec5SDimitry Andric                                              getOperand(0));
69250b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
69260b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
69270b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
69280b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
69290b57cec5SDimitry Andric           SelectSwap = true;
69300b57cec5SDimitry Andric         }
69310b57cec5SDimitry Andric         break;
69320b57cec5SDimitry Andric       case PPC::CRXOR:
69330b57cec5SDimitry Andric         if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
69340b57cec5SDimitry Andric           // xor(x, x) = 0
69350b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRUNSET, SDLoc(MachineNode),
69360b57cec5SDimitry Andric                                            MVT::i1);
69370b57cec5SDimitry Andric         else if (Op1Set)
69380b57cec5SDimitry Andric           // xor(1, y) -> nor(y, y)
69390b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
69400b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
69410b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
69420b57cec5SDimitry Andric         else if (Op2Set)
69430b57cec5SDimitry Andric           // xor(x, 1) -> nor(x, x)
69440b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
69450b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
69460b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
69470b57cec5SDimitry Andric         else if (Op1Unset)
69480b57cec5SDimitry Andric           // xor(0, y) = y
69490b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(1).getNode();
69500b57cec5SDimitry Andric         else if (Op2Unset)
69510b57cec5SDimitry Andric           // xor(x, 0) = x
69520b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
69530b57cec5SDimitry Andric         else if (Op1Not)
69540b57cec5SDimitry Andric           // xor(~x, y) = eqv(x, y)
69550b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CREQV, SDLoc(MachineNode),
69560b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0).
69570b57cec5SDimitry Andric                                                       getOperand(0),
69580b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
69590b57cec5SDimitry Andric         else if (Op2Not)
69600b57cec5SDimitry Andric           // xor(x, ~y) = eqv(x, y)
69610b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CREQV, SDLoc(MachineNode),
69620b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
69630b57cec5SDimitry Andric                                            MachineNode->getOperand(1).
69640b57cec5SDimitry Andric                                              getOperand(0));
69650b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
69660b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CREQV, SDLoc(MachineNode),
69670b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
69680b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
69690b57cec5SDimitry Andric           SelectSwap = true;
69700b57cec5SDimitry Andric         }
69710b57cec5SDimitry Andric         break;
69720b57cec5SDimitry Andric       case PPC::CRNOR:
69730b57cec5SDimitry Andric         if (Op1Set || Op2Set)
69740b57cec5SDimitry Andric           // nor(1, y) -> 0
69750b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRUNSET, SDLoc(MachineNode),
69760b57cec5SDimitry Andric                                            MVT::i1);
69770b57cec5SDimitry Andric         else if (Op1Unset)
69780b57cec5SDimitry Andric           // nor(0, y) = ~y -> nor(y, y)
69790b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
69800b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
69810b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
69820b57cec5SDimitry Andric         else if (Op2Unset)
69830b57cec5SDimitry Andric           // nor(x, 0) = ~x
69840b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
69850b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
69860b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
69870b57cec5SDimitry Andric         else if (Op1Not)
69880b57cec5SDimitry Andric           // nor(~x, y) = andc(x, y)
69890b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRANDC, SDLoc(MachineNode),
69900b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0).
69910b57cec5SDimitry Andric                                                       getOperand(0),
69920b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
69930b57cec5SDimitry Andric         else if (Op2Not)
69940b57cec5SDimitry Andric           // nor(x, ~y) = andc(y, x)
69950b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRANDC, SDLoc(MachineNode),
69960b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1).
69970b57cec5SDimitry Andric                                                       getOperand(0),
69980b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
69990b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
70000b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CROR, SDLoc(MachineNode),
70010b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
70020b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
70030b57cec5SDimitry Andric           SelectSwap = true;
70040b57cec5SDimitry Andric         }
70050b57cec5SDimitry Andric         break;
70060b57cec5SDimitry Andric       case PPC::CREQV:
70070b57cec5SDimitry Andric         if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
70080b57cec5SDimitry Andric           // eqv(x, x) = 1
70090b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRSET, SDLoc(MachineNode),
70100b57cec5SDimitry Andric                                            MVT::i1);
70110b57cec5SDimitry Andric         else if (Op1Set)
70120b57cec5SDimitry Andric           // eqv(1, y) = y
70130b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(1).getNode();
70140b57cec5SDimitry Andric         else if (Op2Set)
70150b57cec5SDimitry Andric           // eqv(x, 1) = x
70160b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
70170b57cec5SDimitry Andric         else if (Op1Unset)
70180b57cec5SDimitry Andric           // eqv(0, y) = ~y -> nor(y, y)
70190b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
70200b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
70210b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
70220b57cec5SDimitry Andric         else if (Op2Unset)
70230b57cec5SDimitry Andric           // eqv(x, 0) = ~x
70240b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
70250b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
70260b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
70270b57cec5SDimitry Andric         else if (Op1Not)
70280b57cec5SDimitry Andric           // eqv(~x, y) = xor(x, y)
70290b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRXOR, SDLoc(MachineNode),
70300b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0).
70310b57cec5SDimitry Andric                                                       getOperand(0),
70320b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
70330b57cec5SDimitry Andric         else if (Op2Not)
70340b57cec5SDimitry Andric           // eqv(x, ~y) = xor(x, y)
70350b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRXOR, SDLoc(MachineNode),
70360b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
70370b57cec5SDimitry Andric                                            MachineNode->getOperand(1).
70380b57cec5SDimitry Andric                                              getOperand(0));
70390b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
70400b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRXOR, SDLoc(MachineNode),
70410b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
70420b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
70430b57cec5SDimitry Andric           SelectSwap = true;
70440b57cec5SDimitry Andric         }
70450b57cec5SDimitry Andric         break;
70460b57cec5SDimitry Andric       case PPC::CRANDC:
70470b57cec5SDimitry Andric         if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
70480b57cec5SDimitry Andric           // andc(x, x) = 0
70490b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRUNSET, SDLoc(MachineNode),
70500b57cec5SDimitry Andric                                            MVT::i1);
70510b57cec5SDimitry Andric         else if (Op1Set)
70520b57cec5SDimitry Andric           // andc(1, y) = ~y
70530b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
70540b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
70550b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
70560b57cec5SDimitry Andric         else if (Op1Unset || Op2Set)
70570b57cec5SDimitry Andric           // andc(0, y) = andc(x, 1) = 0
70580b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRUNSET, SDLoc(MachineNode),
70590b57cec5SDimitry Andric                                            MVT::i1);
70600b57cec5SDimitry Andric         else if (Op2Unset)
70610b57cec5SDimitry Andric           // andc(x, 0) = x
70620b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
70630b57cec5SDimitry Andric         else if (Op1Not)
70640b57cec5SDimitry Andric           // andc(~x, y) = ~(x | y) = nor(x, y)
70650b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
70660b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0).
70670b57cec5SDimitry Andric                                                       getOperand(0),
70680b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
70690b57cec5SDimitry Andric         else if (Op2Not)
70700b57cec5SDimitry Andric           // andc(x, ~y) = x & y
70710b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRAND, SDLoc(MachineNode),
70720b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
70730b57cec5SDimitry Andric                                            MachineNode->getOperand(1).
70740b57cec5SDimitry Andric                                              getOperand(0));
70750b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
70760b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRORC, SDLoc(MachineNode),
70770b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
70780b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
70790b57cec5SDimitry Andric           SelectSwap = true;
70800b57cec5SDimitry Andric         }
70810b57cec5SDimitry Andric         break;
70820b57cec5SDimitry Andric       case PPC::CRORC:
70830b57cec5SDimitry Andric         if (MachineNode->getOperand(0) == MachineNode->getOperand(1))
70840b57cec5SDimitry Andric           // orc(x, x) = 1
70850b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRSET, SDLoc(MachineNode),
70860b57cec5SDimitry Andric                                            MVT::i1);
70870b57cec5SDimitry Andric         else if (Op1Set || Op2Unset)
70880b57cec5SDimitry Andric           // orc(1, y) = orc(x, 0) = 1
70890b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRSET, SDLoc(MachineNode),
70900b57cec5SDimitry Andric                                            MVT::i1);
70910b57cec5SDimitry Andric         else if (Op2Set)
70920b57cec5SDimitry Andric           // orc(x, 1) = x
70930b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(0).getNode();
70940b57cec5SDimitry Andric         else if (Op1Unset)
70950b57cec5SDimitry Andric           // orc(0, y) = ~y
70960b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNOR, SDLoc(MachineNode),
70970b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
70980b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
70990b57cec5SDimitry Andric         else if (Op1Not)
71000b57cec5SDimitry Andric           // orc(~x, y) = ~(x & y) = nand(x, y)
71010b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRNAND, SDLoc(MachineNode),
71020b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0).
71030b57cec5SDimitry Andric                                                       getOperand(0),
71040b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
71050b57cec5SDimitry Andric         else if (Op2Not)
71060b57cec5SDimitry Andric           // orc(x, ~y) = x | y
71070b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CROR, SDLoc(MachineNode),
71080b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(0),
71090b57cec5SDimitry Andric                                            MachineNode->getOperand(1).
71100b57cec5SDimitry Andric                                              getOperand(0));
71110b57cec5SDimitry Andric         else if (AllUsersSelectZero(MachineNode)) {
71120b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(PPC::CRANDC, SDLoc(MachineNode),
71130b57cec5SDimitry Andric                                            MVT::i1, MachineNode->getOperand(1),
71140b57cec5SDimitry Andric                                            MachineNode->getOperand(0));
71150b57cec5SDimitry Andric           SelectSwap = true;
71160b57cec5SDimitry Andric         }
71170b57cec5SDimitry Andric         break;
71180b57cec5SDimitry Andric       case PPC::SELECT_I4:
71190b57cec5SDimitry Andric       case PPC::SELECT_I8:
71200b57cec5SDimitry Andric       case PPC::SELECT_F4:
71210b57cec5SDimitry Andric       case PPC::SELECT_F8:
71220b57cec5SDimitry Andric       case PPC::SELECT_SPE:
71230b57cec5SDimitry Andric       case PPC::SELECT_SPE4:
71240b57cec5SDimitry Andric       case PPC::SELECT_VRRC:
71250b57cec5SDimitry Andric       case PPC::SELECT_VSFRC:
71260b57cec5SDimitry Andric       case PPC::SELECT_VSSRC:
71270b57cec5SDimitry Andric       case PPC::SELECT_VSRC:
71280b57cec5SDimitry Andric         if (Op1Set)
71290b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(1).getNode();
71300b57cec5SDimitry Andric         else if (Op1Unset)
71310b57cec5SDimitry Andric           ResNode = MachineNode->getOperand(2).getNode();
71320b57cec5SDimitry Andric         else if (Op1Not)
71330b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(MachineNode->getMachineOpcode(),
71340b57cec5SDimitry Andric                                            SDLoc(MachineNode),
71350b57cec5SDimitry Andric                                            MachineNode->getValueType(0),
71360b57cec5SDimitry Andric                                            MachineNode->getOperand(0).
71370b57cec5SDimitry Andric                                              getOperand(0),
71380b57cec5SDimitry Andric                                            MachineNode->getOperand(2),
71390b57cec5SDimitry Andric                                            MachineNode->getOperand(1));
71400b57cec5SDimitry Andric         break;
71410b57cec5SDimitry Andric       case PPC::BC:
71420b57cec5SDimitry Andric       case PPC::BCn:
71430b57cec5SDimitry Andric         if (Op1Not)
71440b57cec5SDimitry Andric           ResNode = CurDAG->getMachineNode(Opcode == PPC::BC ? PPC::BCn :
71450b57cec5SDimitry Andric                                                                PPC::BC,
71460b57cec5SDimitry Andric                                            SDLoc(MachineNode),
71470b57cec5SDimitry Andric                                            MVT::Other,
71480b57cec5SDimitry Andric                                            MachineNode->getOperand(0).
71490b57cec5SDimitry Andric                                              getOperand(0),
71500b57cec5SDimitry Andric                                            MachineNode->getOperand(1),
71510b57cec5SDimitry Andric                                            MachineNode->getOperand(2));
71520b57cec5SDimitry Andric         // FIXME: Handle Op1Set, Op1Unset here too.
71530b57cec5SDimitry Andric         break;
71540b57cec5SDimitry Andric       }
71550b57cec5SDimitry Andric 
71560b57cec5SDimitry Andric       // If we're inverting this node because it is used only by selects that
71570b57cec5SDimitry Andric       // we'd like to swap, then swap the selects before the node replacement.
71580b57cec5SDimitry Andric       if (SelectSwap)
71590b57cec5SDimitry Andric         SwapAllSelectUsers(MachineNode);
71600b57cec5SDimitry Andric 
71610b57cec5SDimitry Andric       if (ResNode != MachineNode) {
71620b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "CR Peephole replacing:\nOld:    ");
71630b57cec5SDimitry Andric         LLVM_DEBUG(MachineNode->dump(CurDAG));
71640b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "\nNew: ");
71650b57cec5SDimitry Andric         LLVM_DEBUG(ResNode->dump(CurDAG));
71660b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "\n");
71670b57cec5SDimitry Andric 
71680b57cec5SDimitry Andric         ReplaceUses(MachineNode, ResNode);
71690b57cec5SDimitry Andric         IsModified = true;
71700b57cec5SDimitry Andric       }
71710b57cec5SDimitry Andric     }
71720b57cec5SDimitry Andric     if (IsModified)
71730b57cec5SDimitry Andric       CurDAG->RemoveDeadNodes();
71740b57cec5SDimitry Andric   } while (IsModified);
71750b57cec5SDimitry Andric }
71760b57cec5SDimitry Andric 
71770b57cec5SDimitry Andric // Gather the set of 32-bit operations that are known to have their
71780b57cec5SDimitry Andric // higher-order 32 bits zero, where ToPromote contains all such operations.
PeepholePPC64ZExtGather(SDValue Op32,SmallPtrSetImpl<SDNode * > & ToPromote)71790b57cec5SDimitry Andric static bool PeepholePPC64ZExtGather(SDValue Op32,
71800b57cec5SDimitry Andric                                     SmallPtrSetImpl<SDNode *> &ToPromote) {
71810b57cec5SDimitry Andric   if (!Op32.isMachineOpcode())
71820b57cec5SDimitry Andric     return false;
71830b57cec5SDimitry Andric 
71840b57cec5SDimitry Andric   // First, check for the "frontier" instructions (those that will clear the
71850b57cec5SDimitry Andric   // higher-order 32 bits.
71860b57cec5SDimitry Andric 
71870b57cec5SDimitry Andric   // For RLWINM and RLWNM, we need to make sure that the mask does not wrap
71880b57cec5SDimitry Andric   // around. If it does not, then these instructions will clear the
71890b57cec5SDimitry Andric   // higher-order bits.
71900b57cec5SDimitry Andric   if ((Op32.getMachineOpcode() == PPC::RLWINM ||
71910b57cec5SDimitry Andric        Op32.getMachineOpcode() == PPC::RLWNM) &&
71920b57cec5SDimitry Andric       Op32.getConstantOperandVal(2) <= Op32.getConstantOperandVal(3)) {
71930b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
71940b57cec5SDimitry Andric     return true;
71950b57cec5SDimitry Andric   }
71960b57cec5SDimitry Andric 
71970b57cec5SDimitry Andric   // SLW and SRW always clear the higher-order bits.
71980b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::SLW ||
71990b57cec5SDimitry Andric       Op32.getMachineOpcode() == PPC::SRW) {
72000b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72010b57cec5SDimitry Andric     return true;
72020b57cec5SDimitry Andric   }
72030b57cec5SDimitry Andric 
72040b57cec5SDimitry Andric   // For LI and LIS, we need the immediate to be positive (so that it is not
72050b57cec5SDimitry Andric   // sign extended).
72060b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::LI ||
72070b57cec5SDimitry Andric       Op32.getMachineOpcode() == PPC::LIS) {
72080b57cec5SDimitry Andric     if (!isUInt<15>(Op32.getConstantOperandVal(0)))
72090b57cec5SDimitry Andric       return false;
72100b57cec5SDimitry Andric 
72110b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72120b57cec5SDimitry Andric     return true;
72130b57cec5SDimitry Andric   }
72140b57cec5SDimitry Andric 
72150b57cec5SDimitry Andric   // LHBRX and LWBRX always clear the higher-order bits.
72160b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::LHBRX ||
72170b57cec5SDimitry Andric       Op32.getMachineOpcode() == PPC::LWBRX) {
72180b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72190b57cec5SDimitry Andric     return true;
72200b57cec5SDimitry Andric   }
72210b57cec5SDimitry Andric 
72220b57cec5SDimitry Andric   // CNT[LT]ZW always produce a 64-bit value in [0,32], and so is zero extended.
72230b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::CNTLZW ||
72240b57cec5SDimitry Andric       Op32.getMachineOpcode() == PPC::CNTTZW) {
72250b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72260b57cec5SDimitry Andric     return true;
72270b57cec5SDimitry Andric   }
72280b57cec5SDimitry Andric 
72290b57cec5SDimitry Andric   // Next, check for those instructions we can look through.
72300b57cec5SDimitry Andric 
72310b57cec5SDimitry Andric   // Assuming the mask does not wrap around, then the higher-order bits are
72320b57cec5SDimitry Andric   // taken directly from the first operand.
72330b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::RLWIMI &&
72340b57cec5SDimitry Andric       Op32.getConstantOperandVal(3) <= Op32.getConstantOperandVal(4)) {
72350b57cec5SDimitry Andric     SmallPtrSet<SDNode *, 16> ToPromote1;
72360b57cec5SDimitry Andric     if (!PeepholePPC64ZExtGather(Op32.getOperand(0), ToPromote1))
72370b57cec5SDimitry Andric       return false;
72380b57cec5SDimitry Andric 
72390b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72400b57cec5SDimitry Andric     ToPromote.insert(ToPromote1.begin(), ToPromote1.end());
72410b57cec5SDimitry Andric     return true;
72420b57cec5SDimitry Andric   }
72430b57cec5SDimitry Andric 
72440b57cec5SDimitry Andric   // For OR, the higher-order bits are zero if that is true for both operands.
72450b57cec5SDimitry Andric   // For SELECT_I4, the same is true (but the relevant operand numbers are
72460b57cec5SDimitry Andric   // shifted by 1).
72470b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::OR ||
72480b57cec5SDimitry Andric       Op32.getMachineOpcode() == PPC::SELECT_I4) {
72490b57cec5SDimitry Andric     unsigned B = Op32.getMachineOpcode() == PPC::SELECT_I4 ? 1 : 0;
72500b57cec5SDimitry Andric     SmallPtrSet<SDNode *, 16> ToPromote1;
72510b57cec5SDimitry Andric     if (!PeepholePPC64ZExtGather(Op32.getOperand(B+0), ToPromote1))
72520b57cec5SDimitry Andric       return false;
72530b57cec5SDimitry Andric     if (!PeepholePPC64ZExtGather(Op32.getOperand(B+1), ToPromote1))
72540b57cec5SDimitry Andric       return false;
72550b57cec5SDimitry Andric 
72560b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72570b57cec5SDimitry Andric     ToPromote.insert(ToPromote1.begin(), ToPromote1.end());
72580b57cec5SDimitry Andric     return true;
72590b57cec5SDimitry Andric   }
72600b57cec5SDimitry Andric 
72610b57cec5SDimitry Andric   // For ORI and ORIS, we need the higher-order bits of the first operand to be
72620b57cec5SDimitry Andric   // zero, and also for the constant to be positive (so that it is not sign
72630b57cec5SDimitry Andric   // extended).
72640b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::ORI ||
72650b57cec5SDimitry Andric       Op32.getMachineOpcode() == PPC::ORIS) {
72660b57cec5SDimitry Andric     SmallPtrSet<SDNode *, 16> ToPromote1;
72670b57cec5SDimitry Andric     if (!PeepholePPC64ZExtGather(Op32.getOperand(0), ToPromote1))
72680b57cec5SDimitry Andric       return false;
72690b57cec5SDimitry Andric     if (!isUInt<15>(Op32.getConstantOperandVal(1)))
72700b57cec5SDimitry Andric       return false;
72710b57cec5SDimitry Andric 
72720b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72730b57cec5SDimitry Andric     ToPromote.insert(ToPromote1.begin(), ToPromote1.end());
72740b57cec5SDimitry Andric     return true;
72750b57cec5SDimitry Andric   }
72760b57cec5SDimitry Andric 
72770b57cec5SDimitry Andric   // The higher-order bits of AND are zero if that is true for at least one of
72780b57cec5SDimitry Andric   // the operands.
72790b57cec5SDimitry Andric   if (Op32.getMachineOpcode() == PPC::AND) {
72800b57cec5SDimitry Andric     SmallPtrSet<SDNode *, 16> ToPromote1, ToPromote2;
72810b57cec5SDimitry Andric     bool Op0OK =
72820b57cec5SDimitry Andric       PeepholePPC64ZExtGather(Op32.getOperand(0), ToPromote1);
72830b57cec5SDimitry Andric     bool Op1OK =
72840b57cec5SDimitry Andric       PeepholePPC64ZExtGather(Op32.getOperand(1), ToPromote2);
72850b57cec5SDimitry Andric     if (!Op0OK && !Op1OK)
72860b57cec5SDimitry Andric       return false;
72870b57cec5SDimitry Andric 
72880b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
72890b57cec5SDimitry Andric 
72900b57cec5SDimitry Andric     if (Op0OK)
72910b57cec5SDimitry Andric       ToPromote.insert(ToPromote1.begin(), ToPromote1.end());
72920b57cec5SDimitry Andric 
72930b57cec5SDimitry Andric     if (Op1OK)
72940b57cec5SDimitry Andric       ToPromote.insert(ToPromote2.begin(), ToPromote2.end());
72950b57cec5SDimitry Andric 
72960b57cec5SDimitry Andric     return true;
72970b57cec5SDimitry Andric   }
72980b57cec5SDimitry Andric 
72990b57cec5SDimitry Andric   // For ANDI and ANDIS, the higher-order bits are zero if either that is true
73000b57cec5SDimitry Andric   // of the first operand, or if the second operand is positive (so that it is
73010b57cec5SDimitry Andric   // not sign extended).
7302480093f4SDimitry Andric   if (Op32.getMachineOpcode() == PPC::ANDI_rec ||
7303480093f4SDimitry Andric       Op32.getMachineOpcode() == PPC::ANDIS_rec) {
73040b57cec5SDimitry Andric     SmallPtrSet<SDNode *, 16> ToPromote1;
73050b57cec5SDimitry Andric     bool Op0OK =
73060b57cec5SDimitry Andric       PeepholePPC64ZExtGather(Op32.getOperand(0), ToPromote1);
73070b57cec5SDimitry Andric     bool Op1OK = isUInt<15>(Op32.getConstantOperandVal(1));
73080b57cec5SDimitry Andric     if (!Op0OK && !Op1OK)
73090b57cec5SDimitry Andric       return false;
73100b57cec5SDimitry Andric 
73110b57cec5SDimitry Andric     ToPromote.insert(Op32.getNode());
73120b57cec5SDimitry Andric 
73130b57cec5SDimitry Andric     if (Op0OK)
73140b57cec5SDimitry Andric       ToPromote.insert(ToPromote1.begin(), ToPromote1.end());
73150b57cec5SDimitry Andric 
73160b57cec5SDimitry Andric     return true;
73170b57cec5SDimitry Andric   }
73180b57cec5SDimitry Andric 
73190b57cec5SDimitry Andric   return false;
73200b57cec5SDimitry Andric }
73210b57cec5SDimitry Andric 
PeepholePPC64ZExt()73220b57cec5SDimitry Andric void PPCDAGToDAGISel::PeepholePPC64ZExt() {
73235ffd83dbSDimitry Andric   if (!Subtarget->isPPC64())
73240b57cec5SDimitry Andric     return;
73250b57cec5SDimitry Andric 
73260b57cec5SDimitry Andric   // When we zero-extend from i32 to i64, we use a pattern like this:
73270b57cec5SDimitry Andric   // def : Pat<(i64 (zext i32:$in)),
73280b57cec5SDimitry Andric   //           (RLDICL (INSERT_SUBREG (i64 (IMPLICIT_DEF)), $in, sub_32),
73290b57cec5SDimitry Andric   //                   0, 32)>;
73300b57cec5SDimitry Andric   // There are several 32-bit shift/rotate instructions, however, that will
73310b57cec5SDimitry Andric   // clear the higher-order bits of their output, rendering the RLDICL
73320b57cec5SDimitry Andric   // unnecessary. When that happens, we remove it here, and redefine the
73330b57cec5SDimitry Andric   // relevant 32-bit operation to be a 64-bit operation.
73340b57cec5SDimitry Andric 
73350b57cec5SDimitry Andric   SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
73360b57cec5SDimitry Andric 
73370b57cec5SDimitry Andric   bool MadeChange = false;
73380b57cec5SDimitry Andric   while (Position != CurDAG->allnodes_begin()) {
73390b57cec5SDimitry Andric     SDNode *N = &*--Position;
73400b57cec5SDimitry Andric     // Skip dead nodes and any non-machine opcodes.
73410b57cec5SDimitry Andric     if (N->use_empty() || !N->isMachineOpcode())
73420b57cec5SDimitry Andric       continue;
73430b57cec5SDimitry Andric 
73440b57cec5SDimitry Andric     if (N->getMachineOpcode() != PPC::RLDICL)
73450b57cec5SDimitry Andric       continue;
73460b57cec5SDimitry Andric 
73470b57cec5SDimitry Andric     if (N->getConstantOperandVal(1) != 0 ||
73480b57cec5SDimitry Andric         N->getConstantOperandVal(2) != 32)
73490b57cec5SDimitry Andric       continue;
73500b57cec5SDimitry Andric 
73510b57cec5SDimitry Andric     SDValue ISR = N->getOperand(0);
73520b57cec5SDimitry Andric     if (!ISR.isMachineOpcode() ||
73530b57cec5SDimitry Andric         ISR.getMachineOpcode() != TargetOpcode::INSERT_SUBREG)
73540b57cec5SDimitry Andric       continue;
73550b57cec5SDimitry Andric 
73560b57cec5SDimitry Andric     if (!ISR.hasOneUse())
73570b57cec5SDimitry Andric       continue;
73580b57cec5SDimitry Andric 
73590b57cec5SDimitry Andric     if (ISR.getConstantOperandVal(2) != PPC::sub_32)
73600b57cec5SDimitry Andric       continue;
73610b57cec5SDimitry Andric 
73620b57cec5SDimitry Andric     SDValue IDef = ISR.getOperand(0);
73630b57cec5SDimitry Andric     if (!IDef.isMachineOpcode() ||
73640b57cec5SDimitry Andric         IDef.getMachineOpcode() != TargetOpcode::IMPLICIT_DEF)
73650b57cec5SDimitry Andric       continue;
73660b57cec5SDimitry Andric 
73670b57cec5SDimitry Andric     // We now know that we're looking at a canonical i32 -> i64 zext. See if we
73680b57cec5SDimitry Andric     // can get rid of it.
73690b57cec5SDimitry Andric 
73700b57cec5SDimitry Andric     SDValue Op32 = ISR->getOperand(1);
73710b57cec5SDimitry Andric     if (!Op32.isMachineOpcode())
73720b57cec5SDimitry Andric       continue;
73730b57cec5SDimitry Andric 
73740b57cec5SDimitry Andric     // There are some 32-bit instructions that always clear the high-order 32
73750b57cec5SDimitry Andric     // bits, there are also some instructions (like AND) that we can look
73760b57cec5SDimitry Andric     // through.
73770b57cec5SDimitry Andric     SmallPtrSet<SDNode *, 16> ToPromote;
73780b57cec5SDimitry Andric     if (!PeepholePPC64ZExtGather(Op32, ToPromote))
73790b57cec5SDimitry Andric       continue;
73800b57cec5SDimitry Andric 
73810b57cec5SDimitry Andric     // If the ToPromote set contains nodes that have uses outside of the set
73820b57cec5SDimitry Andric     // (except for the original INSERT_SUBREG), then abort the transformation.
73830b57cec5SDimitry Andric     bool OutsideUse = false;
73840b57cec5SDimitry Andric     for (SDNode *PN : ToPromote) {
73850b57cec5SDimitry Andric       for (SDNode *UN : PN->uses()) {
73860b57cec5SDimitry Andric         if (!ToPromote.count(UN) && UN != ISR.getNode()) {
73870b57cec5SDimitry Andric           OutsideUse = true;
73880b57cec5SDimitry Andric           break;
73890b57cec5SDimitry Andric         }
73900b57cec5SDimitry Andric       }
73910b57cec5SDimitry Andric 
73920b57cec5SDimitry Andric       if (OutsideUse)
73930b57cec5SDimitry Andric         break;
73940b57cec5SDimitry Andric     }
73950b57cec5SDimitry Andric     if (OutsideUse)
73960b57cec5SDimitry Andric       continue;
73970b57cec5SDimitry Andric 
73980b57cec5SDimitry Andric     MadeChange = true;
73990b57cec5SDimitry Andric 
74000b57cec5SDimitry Andric     // We now know that this zero extension can be removed by promoting to
74010b57cec5SDimitry Andric     // nodes in ToPromote to 64-bit operations, where for operations in the
74020b57cec5SDimitry Andric     // frontier of the set, we need to insert INSERT_SUBREGs for their
74030b57cec5SDimitry Andric     // operands.
74040b57cec5SDimitry Andric     for (SDNode *PN : ToPromote) {
74050b57cec5SDimitry Andric       unsigned NewOpcode;
74060b57cec5SDimitry Andric       switch (PN->getMachineOpcode()) {
74070b57cec5SDimitry Andric       default:
74080b57cec5SDimitry Andric         llvm_unreachable("Don't know the 64-bit variant of this instruction");
74090b57cec5SDimitry Andric       case PPC::RLWINM:    NewOpcode = PPC::RLWINM8; break;
74100b57cec5SDimitry Andric       case PPC::RLWNM:     NewOpcode = PPC::RLWNM8; break;
74110b57cec5SDimitry Andric       case PPC::SLW:       NewOpcode = PPC::SLW8; break;
74120b57cec5SDimitry Andric       case PPC::SRW:       NewOpcode = PPC::SRW8; break;
74130b57cec5SDimitry Andric       case PPC::LI:        NewOpcode = PPC::LI8; break;
74140b57cec5SDimitry Andric       case PPC::LIS:       NewOpcode = PPC::LIS8; break;
74150b57cec5SDimitry Andric       case PPC::LHBRX:     NewOpcode = PPC::LHBRX8; break;
74160b57cec5SDimitry Andric       case PPC::LWBRX:     NewOpcode = PPC::LWBRX8; break;
74170b57cec5SDimitry Andric       case PPC::CNTLZW:    NewOpcode = PPC::CNTLZW8; break;
74180b57cec5SDimitry Andric       case PPC::CNTTZW:    NewOpcode = PPC::CNTTZW8; break;
74190b57cec5SDimitry Andric       case PPC::RLWIMI:    NewOpcode = PPC::RLWIMI8; break;
74200b57cec5SDimitry Andric       case PPC::OR:        NewOpcode = PPC::OR8; break;
74210b57cec5SDimitry Andric       case PPC::SELECT_I4: NewOpcode = PPC::SELECT_I8; break;
74220b57cec5SDimitry Andric       case PPC::ORI:       NewOpcode = PPC::ORI8; break;
74230b57cec5SDimitry Andric       case PPC::ORIS:      NewOpcode = PPC::ORIS8; break;
74240b57cec5SDimitry Andric       case PPC::AND:       NewOpcode = PPC::AND8; break;
7425480093f4SDimitry Andric       case PPC::ANDI_rec:
7426480093f4SDimitry Andric         NewOpcode = PPC::ANDI8_rec;
7427480093f4SDimitry Andric         break;
7428480093f4SDimitry Andric       case PPC::ANDIS_rec:
7429480093f4SDimitry Andric         NewOpcode = PPC::ANDIS8_rec;
7430480093f4SDimitry Andric         break;
74310b57cec5SDimitry Andric       }
74320b57cec5SDimitry Andric 
74330b57cec5SDimitry Andric       // Note: During the replacement process, the nodes will be in an
74340b57cec5SDimitry Andric       // inconsistent state (some instructions will have operands with values
74350b57cec5SDimitry Andric       // of the wrong type). Once done, however, everything should be right
74360b57cec5SDimitry Andric       // again.
74370b57cec5SDimitry Andric 
74380b57cec5SDimitry Andric       SmallVector<SDValue, 4> Ops;
74390b57cec5SDimitry Andric       for (const SDValue &V : PN->ops()) {
74400b57cec5SDimitry Andric         if (!ToPromote.count(V.getNode()) && V.getValueType() == MVT::i32 &&
74410b57cec5SDimitry Andric             !isa<ConstantSDNode>(V)) {
74420b57cec5SDimitry Andric           SDValue ReplOpOps[] = { ISR.getOperand(0), V, ISR.getOperand(2) };
74430b57cec5SDimitry Andric           SDNode *ReplOp =
74440b57cec5SDimitry Andric             CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, SDLoc(V),
74450b57cec5SDimitry Andric                                    ISR.getNode()->getVTList(), ReplOpOps);
74460b57cec5SDimitry Andric           Ops.push_back(SDValue(ReplOp, 0));
74470b57cec5SDimitry Andric         } else {
74480b57cec5SDimitry Andric           Ops.push_back(V);
74490b57cec5SDimitry Andric         }
74500b57cec5SDimitry Andric       }
74510b57cec5SDimitry Andric 
74520b57cec5SDimitry Andric       // Because all to-be-promoted nodes only have users that are other
74530b57cec5SDimitry Andric       // promoted nodes (or the original INSERT_SUBREG), we can safely replace
74540b57cec5SDimitry Andric       // the i32 result value type with i64.
74550b57cec5SDimitry Andric 
74560b57cec5SDimitry Andric       SmallVector<EVT, 2> NewVTs;
74570b57cec5SDimitry Andric       SDVTList VTs = PN->getVTList();
74580b57cec5SDimitry Andric       for (unsigned i = 0, ie = VTs.NumVTs; i != ie; ++i)
74590b57cec5SDimitry Andric         if (VTs.VTs[i] == MVT::i32)
74600b57cec5SDimitry Andric           NewVTs.push_back(MVT::i64);
74610b57cec5SDimitry Andric         else
74620b57cec5SDimitry Andric           NewVTs.push_back(VTs.VTs[i]);
74630b57cec5SDimitry Andric 
74640b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "PPC64 ZExt Peephole morphing:\nOld:    ");
74650b57cec5SDimitry Andric       LLVM_DEBUG(PN->dump(CurDAG));
74660b57cec5SDimitry Andric 
74670b57cec5SDimitry Andric       CurDAG->SelectNodeTo(PN, NewOpcode, CurDAG->getVTList(NewVTs), Ops);
74680b57cec5SDimitry Andric 
74690b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\nNew: ");
74700b57cec5SDimitry Andric       LLVM_DEBUG(PN->dump(CurDAG));
74710b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "\n");
74720b57cec5SDimitry Andric     }
74730b57cec5SDimitry Andric 
74740b57cec5SDimitry Andric     // Now we replace the original zero extend and its associated INSERT_SUBREG
74750b57cec5SDimitry Andric     // with the value feeding the INSERT_SUBREG (which has now been promoted to
74760b57cec5SDimitry Andric     // return an i64).
74770b57cec5SDimitry Andric 
74780b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "PPC64 ZExt Peephole replacing:\nOld:    ");
74790b57cec5SDimitry Andric     LLVM_DEBUG(N->dump(CurDAG));
74800b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\nNew: ");
74810b57cec5SDimitry Andric     LLVM_DEBUG(Op32.getNode()->dump(CurDAG));
74820b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n");
74830b57cec5SDimitry Andric 
74840b57cec5SDimitry Andric     ReplaceUses(N, Op32.getNode());
74850b57cec5SDimitry Andric   }
74860b57cec5SDimitry Andric 
74870b57cec5SDimitry Andric   if (MadeChange)
74880b57cec5SDimitry Andric     CurDAG->RemoveDeadNodes();
74890b57cec5SDimitry Andric }
74900b57cec5SDimitry Andric 
isVSXSwap(SDValue N)7491fe6060f1SDimitry Andric static bool isVSXSwap(SDValue N) {
7492fe6060f1SDimitry Andric   if (!N->isMachineOpcode())
7493fe6060f1SDimitry Andric     return false;
7494fe6060f1SDimitry Andric   unsigned Opc = N->getMachineOpcode();
7495fe6060f1SDimitry Andric 
7496fe6060f1SDimitry Andric   // Single-operand XXPERMDI or the regular XXPERMDI/XXSLDWI where the immediate
7497fe6060f1SDimitry Andric   // operand is 2.
7498fe6060f1SDimitry Andric   if (Opc == PPC::XXPERMDIs) {
7499fe6060f1SDimitry Andric     return isa<ConstantSDNode>(N->getOperand(1)) &&
7500fe6060f1SDimitry Andric            N->getConstantOperandVal(1) == 2;
7501fe6060f1SDimitry Andric   } else if (Opc == PPC::XXPERMDI || Opc == PPC::XXSLDWI) {
7502fe6060f1SDimitry Andric     return N->getOperand(0) == N->getOperand(1) &&
7503fe6060f1SDimitry Andric            isa<ConstantSDNode>(N->getOperand(2)) &&
7504fe6060f1SDimitry Andric            N->getConstantOperandVal(2) == 2;
7505fe6060f1SDimitry Andric   }
7506fe6060f1SDimitry Andric 
7507fe6060f1SDimitry Andric   return false;
7508fe6060f1SDimitry Andric }
7509fe6060f1SDimitry Andric 
7510fe6060f1SDimitry Andric // TODO: Make this complete and replace with a table-gen bit.
isLaneInsensitive(SDValue N)7511fe6060f1SDimitry Andric static bool isLaneInsensitive(SDValue N) {
7512fe6060f1SDimitry Andric   if (!N->isMachineOpcode())
7513fe6060f1SDimitry Andric     return false;
7514fe6060f1SDimitry Andric   unsigned Opc = N->getMachineOpcode();
7515fe6060f1SDimitry Andric 
7516fe6060f1SDimitry Andric   switch (Opc) {
7517fe6060f1SDimitry Andric   default:
7518fe6060f1SDimitry Andric     return false;
7519fe6060f1SDimitry Andric   case PPC::VAVGSB:
7520fe6060f1SDimitry Andric   case PPC::VAVGUB:
7521fe6060f1SDimitry Andric   case PPC::VAVGSH:
7522fe6060f1SDimitry Andric   case PPC::VAVGUH:
7523fe6060f1SDimitry Andric   case PPC::VAVGSW:
7524fe6060f1SDimitry Andric   case PPC::VAVGUW:
7525fe6060f1SDimitry Andric   case PPC::VMAXFP:
7526fe6060f1SDimitry Andric   case PPC::VMAXSB:
7527fe6060f1SDimitry Andric   case PPC::VMAXUB:
7528fe6060f1SDimitry Andric   case PPC::VMAXSH:
7529fe6060f1SDimitry Andric   case PPC::VMAXUH:
7530fe6060f1SDimitry Andric   case PPC::VMAXSW:
7531fe6060f1SDimitry Andric   case PPC::VMAXUW:
7532fe6060f1SDimitry Andric   case PPC::VMINFP:
7533fe6060f1SDimitry Andric   case PPC::VMINSB:
7534fe6060f1SDimitry Andric   case PPC::VMINUB:
7535fe6060f1SDimitry Andric   case PPC::VMINSH:
7536fe6060f1SDimitry Andric   case PPC::VMINUH:
7537fe6060f1SDimitry Andric   case PPC::VMINSW:
7538fe6060f1SDimitry Andric   case PPC::VMINUW:
7539fe6060f1SDimitry Andric   case PPC::VADDFP:
7540fe6060f1SDimitry Andric   case PPC::VADDUBM:
7541fe6060f1SDimitry Andric   case PPC::VADDUHM:
7542fe6060f1SDimitry Andric   case PPC::VADDUWM:
7543fe6060f1SDimitry Andric   case PPC::VSUBFP:
7544fe6060f1SDimitry Andric   case PPC::VSUBUBM:
7545fe6060f1SDimitry Andric   case PPC::VSUBUHM:
7546fe6060f1SDimitry Andric   case PPC::VSUBUWM:
7547fe6060f1SDimitry Andric   case PPC::VAND:
7548fe6060f1SDimitry Andric   case PPC::VANDC:
7549fe6060f1SDimitry Andric   case PPC::VOR:
7550fe6060f1SDimitry Andric   case PPC::VORC:
7551fe6060f1SDimitry Andric   case PPC::VXOR:
7552fe6060f1SDimitry Andric   case PPC::VNOR:
7553fe6060f1SDimitry Andric   case PPC::VMULUWM:
7554fe6060f1SDimitry Andric     return true;
7555fe6060f1SDimitry Andric   }
7556fe6060f1SDimitry Andric }
7557fe6060f1SDimitry Andric 
7558fe6060f1SDimitry Andric // Try to simplify (xxswap (vec-op (xxswap) (xxswap))) where vec-op is
7559fe6060f1SDimitry Andric // lane-insensitive.
reduceVSXSwap(SDNode * N,SelectionDAG * DAG)7560fe6060f1SDimitry Andric static void reduceVSXSwap(SDNode *N, SelectionDAG *DAG) {
7561fe6060f1SDimitry Andric   // Our desired xxswap might be source of COPY_TO_REGCLASS.
7562fe6060f1SDimitry Andric   // TODO: Can we put this a common method for DAG?
7563fe6060f1SDimitry Andric   auto SkipRCCopy = [](SDValue V) {
7564fe6060f1SDimitry Andric     while (V->isMachineOpcode() &&
7565fe6060f1SDimitry Andric            V->getMachineOpcode() == TargetOpcode::COPY_TO_REGCLASS) {
7566fe6060f1SDimitry Andric       // All values in the chain should have single use.
7567fe6060f1SDimitry Andric       if (V->use_empty() || !V->use_begin()->isOnlyUserOf(V.getNode()))
7568fe6060f1SDimitry Andric         return SDValue();
7569fe6060f1SDimitry Andric       V = V->getOperand(0);
7570fe6060f1SDimitry Andric     }
7571fe6060f1SDimitry Andric     return V.hasOneUse() ? V : SDValue();
7572fe6060f1SDimitry Andric   };
7573fe6060f1SDimitry Andric 
7574fe6060f1SDimitry Andric   SDValue VecOp = SkipRCCopy(N->getOperand(0));
7575fe6060f1SDimitry Andric   if (!VecOp || !isLaneInsensitive(VecOp))
7576fe6060f1SDimitry Andric     return;
7577fe6060f1SDimitry Andric 
7578fe6060f1SDimitry Andric   SDValue LHS = SkipRCCopy(VecOp.getOperand(0)),
7579fe6060f1SDimitry Andric           RHS = SkipRCCopy(VecOp.getOperand(1));
7580fe6060f1SDimitry Andric   if (!LHS || !RHS || !isVSXSwap(LHS) || !isVSXSwap(RHS))
7581fe6060f1SDimitry Andric     return;
7582fe6060f1SDimitry Andric 
7583fe6060f1SDimitry Andric   // These swaps may still have chain-uses here, count on dead code elimination
7584fe6060f1SDimitry Andric   // in following passes to remove them.
7585fe6060f1SDimitry Andric   DAG->ReplaceAllUsesOfValueWith(LHS, LHS.getOperand(0));
7586fe6060f1SDimitry Andric   DAG->ReplaceAllUsesOfValueWith(RHS, RHS.getOperand(0));
7587fe6060f1SDimitry Andric   DAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), N->getOperand(0));
7588fe6060f1SDimitry Andric }
7589fe6060f1SDimitry Andric 
7590*0fca6ea1SDimitry Andric // Check if an SDValue has the 'aix-small-tls' global variable attribute.
hasAIXSmallTLSAttr(SDValue Val)7591*0fca6ea1SDimitry Andric static bool hasAIXSmallTLSAttr(SDValue Val) {
7592*0fca6ea1SDimitry Andric   if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Val))
7593*0fca6ea1SDimitry Andric     if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(GA->getGlobal()))
7594*0fca6ea1SDimitry Andric       if (GV->hasAttribute("aix-small-tls"))
7595*0fca6ea1SDimitry Andric         return true;
7596*0fca6ea1SDimitry Andric 
7597*0fca6ea1SDimitry Andric   return false;
7598*0fca6ea1SDimitry Andric }
7599*0fca6ea1SDimitry Andric 
7600*0fca6ea1SDimitry Andric // Is an ADDI eligible for folding for non-TOC-based local-[exec|dynamic]
7601*0fca6ea1SDimitry Andric // accesses?
isEligibleToFoldADDIForFasterLocalAccesses(SelectionDAG * DAG,SDValue ADDIToFold)7602*0fca6ea1SDimitry Andric static bool isEligibleToFoldADDIForFasterLocalAccesses(SelectionDAG *DAG,
7603*0fca6ea1SDimitry Andric                                                        SDValue ADDIToFold) {
7604*0fca6ea1SDimitry Andric   // Check if ADDIToFold (the ADDI that we want to fold into local-exec
7605*0fca6ea1SDimitry Andric   // accesses), is truly an ADDI.
7606*0fca6ea1SDimitry Andric   if (!ADDIToFold.isMachineOpcode() ||
7607*0fca6ea1SDimitry Andric       (ADDIToFold.getMachineOpcode() != PPC::ADDI8))
7608*0fca6ea1SDimitry Andric     return false;
7609*0fca6ea1SDimitry Andric 
7610*0fca6ea1SDimitry Andric   // Folding is only allowed for the AIX small-local-[exec|dynamic] TLS target
7611*0fca6ea1SDimitry Andric   // attribute or when the 'aix-small-tls' global variable attribute is present.
7612*0fca6ea1SDimitry Andric   const PPCSubtarget &Subtarget =
7613*0fca6ea1SDimitry Andric       DAG->getMachineFunction().getSubtarget<PPCSubtarget>();
7614*0fca6ea1SDimitry Andric   SDValue TLSVarNode = ADDIToFold.getOperand(1);
7615*0fca6ea1SDimitry Andric   if (!(Subtarget.hasAIXSmallLocalDynamicTLS() ||
7616*0fca6ea1SDimitry Andric         Subtarget.hasAIXSmallLocalExecTLS() || hasAIXSmallTLSAttr(TLSVarNode)))
7617*0fca6ea1SDimitry Andric     return false;
7618*0fca6ea1SDimitry Andric 
7619*0fca6ea1SDimitry Andric   // The second operand of the ADDIToFold should be the global TLS address
7620*0fca6ea1SDimitry Andric   // (the local-exec TLS variable). We only perform the folding if the TLS
7621*0fca6ea1SDimitry Andric   // variable is the second operand.
7622*0fca6ea1SDimitry Andric   GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(TLSVarNode);
7623*0fca6ea1SDimitry Andric   if (!GA)
7624*0fca6ea1SDimitry Andric     return false;
7625*0fca6ea1SDimitry Andric 
7626*0fca6ea1SDimitry Andric   if (DAG->getTarget().getTLSModel(GA->getGlobal()) == TLSModel::LocalExec) {
7627*0fca6ea1SDimitry Andric     // The first operand of the ADDIToFold should be the thread pointer.
7628*0fca6ea1SDimitry Andric     // This transformation is only performed if the first operand of the
7629*0fca6ea1SDimitry Andric     // addi is the thread pointer.
7630*0fca6ea1SDimitry Andric     SDValue TPRegNode = ADDIToFold.getOperand(0);
7631*0fca6ea1SDimitry Andric     RegisterSDNode *TPReg = dyn_cast<RegisterSDNode>(TPRegNode.getNode());
7632*0fca6ea1SDimitry Andric     if (!TPReg || (TPReg->getReg() != Subtarget.getThreadPointerRegister()))
7633*0fca6ea1SDimitry Andric       return false;
7634*0fca6ea1SDimitry Andric   }
7635*0fca6ea1SDimitry Andric 
7636*0fca6ea1SDimitry Andric   // The local-[exec|dynamic] TLS variable should only have the
7637*0fca6ea1SDimitry Andric   // [MO_TPREL_FLAG|MO_TLSLD_FLAG] target flags, so this optimization is not
7638*0fca6ea1SDimitry Andric   // performed otherwise if the flag is not set.
7639*0fca6ea1SDimitry Andric   unsigned TargetFlags = GA->getTargetFlags();
7640*0fca6ea1SDimitry Andric   if (!(TargetFlags == PPCII::MO_TPREL_FLAG ||
7641*0fca6ea1SDimitry Andric         TargetFlags == PPCII::MO_TLSLD_FLAG))
7642*0fca6ea1SDimitry Andric     return false;
7643*0fca6ea1SDimitry Andric 
7644*0fca6ea1SDimitry Andric   // If all conditions are satisfied, the ADDI is valid for folding.
7645*0fca6ea1SDimitry Andric   return true;
7646*0fca6ea1SDimitry Andric }
7647*0fca6ea1SDimitry Andric 
7648*0fca6ea1SDimitry Andric // For non-TOC-based local-[exec|dynamic] access where an addi is feeding into
7649*0fca6ea1SDimitry Andric // another addi, fold this sequence into a single addi if possible. Before this
7650*0fca6ea1SDimitry Andric // optimization, the sequence appears as:
7651*0fca6ea1SDimitry Andric //    addi rN, r13, sym@[le|ld]
7652*0fca6ea1SDimitry Andric //    addi rM, rN, imm
7653*0fca6ea1SDimitry Andric // After this optimization, we can fold the two addi into a single one:
7654*0fca6ea1SDimitry Andric //    addi rM, r13, sym@[le|ld] + imm
foldADDIForFasterLocalAccesses(SDNode * N,SelectionDAG * DAG)7655*0fca6ea1SDimitry Andric static void foldADDIForFasterLocalAccesses(SDNode *N, SelectionDAG *DAG) {
7656*0fca6ea1SDimitry Andric   if (N->getMachineOpcode() != PPC::ADDI8)
7657*0fca6ea1SDimitry Andric     return;
7658*0fca6ea1SDimitry Andric 
7659*0fca6ea1SDimitry Andric   // InitialADDI is the addi feeding into N (also an addi), and the addi that
7660*0fca6ea1SDimitry Andric   // we want optimized out.
7661*0fca6ea1SDimitry Andric   SDValue InitialADDI = N->getOperand(0);
7662*0fca6ea1SDimitry Andric 
7663*0fca6ea1SDimitry Andric   if (!isEligibleToFoldADDIForFasterLocalAccesses(DAG, InitialADDI))
7664*0fca6ea1SDimitry Andric     return;
7665*0fca6ea1SDimitry Andric 
7666*0fca6ea1SDimitry Andric   // The second operand of the InitialADDI should be the global TLS address
7667*0fca6ea1SDimitry Andric   // (the local-[exec|dynamic] TLS variable), with the
7668*0fca6ea1SDimitry Andric   // [MO_TPREL_FLAG|MO_TLSLD_FLAG] target flag. This has been checked in
7669*0fca6ea1SDimitry Andric   // isEligibleToFoldADDIForFasterLocalAccesses().
7670*0fca6ea1SDimitry Andric   SDValue TLSVarNode = InitialADDI.getOperand(1);
7671*0fca6ea1SDimitry Andric   GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(TLSVarNode);
7672*0fca6ea1SDimitry Andric   assert(GA && "Expecting a valid GlobalAddressSDNode when folding addi into "
7673*0fca6ea1SDimitry Andric                "local-[exec|dynamic] accesses!");
7674*0fca6ea1SDimitry Andric   unsigned TargetFlags = GA->getTargetFlags();
7675*0fca6ea1SDimitry Andric 
7676*0fca6ea1SDimitry Andric   // The second operand of the addi that we want to preserve will be an
7677*0fca6ea1SDimitry Andric   // immediate. We add this immediate, together with the address of the TLS
7678*0fca6ea1SDimitry Andric   // variable found in InitialADDI, in order to preserve the correct TLS address
7679*0fca6ea1SDimitry Andric   // information during assembly printing. The offset is likely to be non-zero
7680*0fca6ea1SDimitry Andric   // when we end up in this case.
7681*0fca6ea1SDimitry Andric   int Offset = N->getConstantOperandVal(1);
7682*0fca6ea1SDimitry Andric   TLSVarNode = DAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(GA), MVT::i64,
7683*0fca6ea1SDimitry Andric                                            Offset, TargetFlags);
7684*0fca6ea1SDimitry Andric 
7685*0fca6ea1SDimitry Andric   (void)DAG->UpdateNodeOperands(N, InitialADDI.getOperand(0), TLSVarNode);
7686*0fca6ea1SDimitry Andric   if (InitialADDI.getNode()->use_empty())
7687*0fca6ea1SDimitry Andric     DAG->RemoveDeadNode(InitialADDI.getNode());
7688*0fca6ea1SDimitry Andric }
7689*0fca6ea1SDimitry Andric 
PeepholePPC64()76900b57cec5SDimitry Andric void PPCDAGToDAGISel::PeepholePPC64() {
76910b57cec5SDimitry Andric   SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end();
76920b57cec5SDimitry Andric 
76930b57cec5SDimitry Andric   while (Position != CurDAG->allnodes_begin()) {
76940b57cec5SDimitry Andric     SDNode *N = &*--Position;
76950b57cec5SDimitry Andric     // Skip dead nodes and any non-machine opcodes.
76960b57cec5SDimitry Andric     if (N->use_empty() || !N->isMachineOpcode())
76970b57cec5SDimitry Andric       continue;
76980b57cec5SDimitry Andric 
7699fe6060f1SDimitry Andric     if (isVSXSwap(SDValue(N, 0)))
7700fe6060f1SDimitry Andric       reduceVSXSwap(N, CurDAG);
7701fe6060f1SDimitry Andric 
7702*0fca6ea1SDimitry Andric     // This optimization is performed for non-TOC-based local-[exec|dynamic]
7703*0fca6ea1SDimitry Andric     // accesses.
7704*0fca6ea1SDimitry Andric     foldADDIForFasterLocalAccesses(N, CurDAG);
7705*0fca6ea1SDimitry Andric 
77060b57cec5SDimitry Andric     unsigned FirstOp;
77070b57cec5SDimitry Andric     unsigned StorageOpcode = N->getMachineOpcode();
77080b57cec5SDimitry Andric     bool RequiresMod4Offset = false;
77090b57cec5SDimitry Andric 
77100b57cec5SDimitry Andric     switch (StorageOpcode) {
77110b57cec5SDimitry Andric     default: continue;
77120b57cec5SDimitry Andric 
77130b57cec5SDimitry Andric     case PPC::LWA:
77140b57cec5SDimitry Andric     case PPC::LD:
77150b57cec5SDimitry Andric     case PPC::DFLOADf64:
77160b57cec5SDimitry Andric     case PPC::DFLOADf32:
77170b57cec5SDimitry Andric       RequiresMod4Offset = true;
7718bdd1243dSDimitry Andric       [[fallthrough]];
77190b57cec5SDimitry Andric     case PPC::LBZ:
77200b57cec5SDimitry Andric     case PPC::LBZ8:
77210b57cec5SDimitry Andric     case PPC::LFD:
77220b57cec5SDimitry Andric     case PPC::LFS:
77230b57cec5SDimitry Andric     case PPC::LHA:
77240b57cec5SDimitry Andric     case PPC::LHA8:
77250b57cec5SDimitry Andric     case PPC::LHZ:
77260b57cec5SDimitry Andric     case PPC::LHZ8:
77270b57cec5SDimitry Andric     case PPC::LWZ:
77280b57cec5SDimitry Andric     case PPC::LWZ8:
77290b57cec5SDimitry Andric       FirstOp = 0;
77300b57cec5SDimitry Andric       break;
77310b57cec5SDimitry Andric 
77320b57cec5SDimitry Andric     case PPC::STD:
77330b57cec5SDimitry Andric     case PPC::DFSTOREf64:
77340b57cec5SDimitry Andric     case PPC::DFSTOREf32:
77350b57cec5SDimitry Andric       RequiresMod4Offset = true;
7736bdd1243dSDimitry Andric       [[fallthrough]];
77370b57cec5SDimitry Andric     case PPC::STB:
77380b57cec5SDimitry Andric     case PPC::STB8:
77390b57cec5SDimitry Andric     case PPC::STFD:
77400b57cec5SDimitry Andric     case PPC::STFS:
77410b57cec5SDimitry Andric     case PPC::STH:
77420b57cec5SDimitry Andric     case PPC::STH8:
77430b57cec5SDimitry Andric     case PPC::STW:
77440b57cec5SDimitry Andric     case PPC::STW8:
77450b57cec5SDimitry Andric       FirstOp = 1;
77460b57cec5SDimitry Andric       break;
77470b57cec5SDimitry Andric     }
77480b57cec5SDimitry Andric 
77490b57cec5SDimitry Andric     // If this is a load or store with a zero offset, or within the alignment,
77500b57cec5SDimitry Andric     // we may be able to fold an add-immediate into the memory operation.
77510b57cec5SDimitry Andric     // The check against alignment is below, as it can't occur until we check
77520b57cec5SDimitry Andric     // the arguments to N
77530b57cec5SDimitry Andric     if (!isa<ConstantSDNode>(N->getOperand(FirstOp)))
77540b57cec5SDimitry Andric       continue;
77550b57cec5SDimitry Andric 
77560b57cec5SDimitry Andric     SDValue Base = N->getOperand(FirstOp + 1);
77570b57cec5SDimitry Andric     if (!Base.isMachineOpcode())
77580b57cec5SDimitry Andric       continue;
77590b57cec5SDimitry Andric 
77600b57cec5SDimitry Andric     unsigned Flags = 0;
77610b57cec5SDimitry Andric     bool ReplaceFlags = true;
77620b57cec5SDimitry Andric 
77630b57cec5SDimitry Andric     // When the feeding operation is an add-immediate of some sort,
77640b57cec5SDimitry Andric     // determine whether we need to add relocation information to the
77650b57cec5SDimitry Andric     // target flags on the immediate operand when we fold it into the
77660b57cec5SDimitry Andric     // load instruction.
77670b57cec5SDimitry Andric     //
7768*0fca6ea1SDimitry Andric     // For something like ADDItocL8, the relocation information is
77690b57cec5SDimitry Andric     // inferred from the opcode; when we process it in the AsmPrinter,
77700b57cec5SDimitry Andric     // we add the necessary relocation there.  A load, though, can receive
77710b57cec5SDimitry Andric     // relocation from various flavors of ADDIxxx, so we need to carry
77720b57cec5SDimitry Andric     // the relocation information in the target flags.
77730b57cec5SDimitry Andric     switch (Base.getMachineOpcode()) {
77740b57cec5SDimitry Andric     default: continue;
77750b57cec5SDimitry Andric 
77760b57cec5SDimitry Andric     case PPC::ADDI8:
77770b57cec5SDimitry Andric     case PPC::ADDI:
77780b57cec5SDimitry Andric       // In some cases (such as TLS) the relocation information
77790b57cec5SDimitry Andric       // is already in place on the operand, so copying the operand
77800b57cec5SDimitry Andric       // is sufficient.
77810b57cec5SDimitry Andric       ReplaceFlags = false;
77820b57cec5SDimitry Andric       break;
77830b57cec5SDimitry Andric     case PPC::ADDIdtprelL:
77840b57cec5SDimitry Andric       Flags = PPCII::MO_DTPREL_LO;
77850b57cec5SDimitry Andric       break;
77860b57cec5SDimitry Andric     case PPC::ADDItlsldL:
77870b57cec5SDimitry Andric       Flags = PPCII::MO_TLSLD_LO;
77880b57cec5SDimitry Andric       break;
7789*0fca6ea1SDimitry Andric     case PPC::ADDItocL8:
7790*0fca6ea1SDimitry Andric       // Skip the following peephole optimizations for ADDItocL8 on AIX which
7791*0fca6ea1SDimitry Andric       // is used for toc-data access.
7792*0fca6ea1SDimitry Andric       if (Subtarget->isAIXABI())
7793*0fca6ea1SDimitry Andric         continue;
77940b57cec5SDimitry Andric       Flags = PPCII::MO_TOC_LO;
77950b57cec5SDimitry Andric       break;
77960b57cec5SDimitry Andric     }
77970b57cec5SDimitry Andric 
77980b57cec5SDimitry Andric     SDValue ImmOpnd = Base.getOperand(1);
77990b57cec5SDimitry Andric 
78000b57cec5SDimitry Andric     // On PPC64, the TOC base pointer is guaranteed by the ABI only to have
78010b57cec5SDimitry Andric     // 8-byte alignment, and so we can only use offsets less than 8 (otherwise,
78020b57cec5SDimitry Andric     // we might have needed different @ha relocation values for the offset
78030b57cec5SDimitry Andric     // pointers).
78040b57cec5SDimitry Andric     int MaxDisplacement = 7;
78050b57cec5SDimitry Andric     if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
78060b57cec5SDimitry Andric       const GlobalValue *GV = GA->getGlobal();
78075ffd83dbSDimitry Andric       Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
78085ffd83dbSDimitry Andric       MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement);
78090b57cec5SDimitry Andric     }
78100b57cec5SDimitry Andric 
78110b57cec5SDimitry Andric     bool UpdateHBase = false;
78120b57cec5SDimitry Andric     SDValue HBase = Base.getOperand(0);
78130b57cec5SDimitry Andric 
78140b57cec5SDimitry Andric     int Offset = N->getConstantOperandVal(FirstOp);
78150b57cec5SDimitry Andric     if (ReplaceFlags) {
78160b57cec5SDimitry Andric       if (Offset < 0 || Offset > MaxDisplacement) {
78170b57cec5SDimitry Andric         // If we have a addi(toc@l)/addis(toc@ha) pair, and the addis has only
78180b57cec5SDimitry Andric         // one use, then we can do this for any offset, we just need to also
78190b57cec5SDimitry Andric         // update the offset (i.e. the symbol addend) on the addis also.
7820*0fca6ea1SDimitry Andric         if (Base.getMachineOpcode() != PPC::ADDItocL8)
78210b57cec5SDimitry Andric           continue;
78220b57cec5SDimitry Andric 
78230b57cec5SDimitry Andric         if (!HBase.isMachineOpcode() ||
78248bcb0991SDimitry Andric             HBase.getMachineOpcode() != PPC::ADDIStocHA8)
78250b57cec5SDimitry Andric           continue;
78260b57cec5SDimitry Andric 
78270b57cec5SDimitry Andric         if (!Base.hasOneUse() || !HBase.hasOneUse())
78280b57cec5SDimitry Andric           continue;
78290b57cec5SDimitry Andric 
78300b57cec5SDimitry Andric         SDValue HImmOpnd = HBase.getOperand(1);
78310b57cec5SDimitry Andric         if (HImmOpnd != ImmOpnd)
78320b57cec5SDimitry Andric           continue;
78330b57cec5SDimitry Andric 
78340b57cec5SDimitry Andric         UpdateHBase = true;
78350b57cec5SDimitry Andric       }
78360b57cec5SDimitry Andric     } else {
78375f757f3fSDimitry Andric       // Global addresses can be folded, but only if they are sufficiently
78385f757f3fSDimitry Andric       // aligned.
78395f757f3fSDimitry Andric       if (RequiresMod4Offset) {
78405f757f3fSDimitry Andric         if (GlobalAddressSDNode *GA =
78415f757f3fSDimitry Andric                 dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
78425f757f3fSDimitry Andric           const GlobalValue *GV = GA->getGlobal();
78435f757f3fSDimitry Andric           Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
78445f757f3fSDimitry Andric           if (Alignment < 4)
78455f757f3fSDimitry Andric             continue;
78465f757f3fSDimitry Andric         }
78475f757f3fSDimitry Andric       }
78485f757f3fSDimitry Andric 
78490b57cec5SDimitry Andric       // If we're directly folding the addend from an addi instruction, then:
78500b57cec5SDimitry Andric       //  1. In general, the offset on the memory access must be zero.
78510b57cec5SDimitry Andric       //  2. If the addend is a constant, then it can be combined with a
78520b57cec5SDimitry Andric       //     non-zero offset, but only if the result meets the encoding
78530b57cec5SDimitry Andric       //     requirements.
78540b57cec5SDimitry Andric       if (auto *C = dyn_cast<ConstantSDNode>(ImmOpnd)) {
78550b57cec5SDimitry Andric         Offset += C->getSExtValue();
78560b57cec5SDimitry Andric 
78570b57cec5SDimitry Andric         if (RequiresMod4Offset && (Offset % 4) != 0)
78580b57cec5SDimitry Andric           continue;
78590b57cec5SDimitry Andric 
78600b57cec5SDimitry Andric         if (!isInt<16>(Offset))
78610b57cec5SDimitry Andric           continue;
78620b57cec5SDimitry Andric 
78630b57cec5SDimitry Andric         ImmOpnd = CurDAG->getTargetConstant(Offset, SDLoc(ImmOpnd),
78640b57cec5SDimitry Andric                                             ImmOpnd.getValueType());
78650b57cec5SDimitry Andric       } else if (Offset != 0) {
7866*0fca6ea1SDimitry Andric         // This optimization is performed for non-TOC-based local-[exec|dynamic]
7867*0fca6ea1SDimitry Andric         // accesses.
7868*0fca6ea1SDimitry Andric         if (isEligibleToFoldADDIForFasterLocalAccesses(CurDAG, Base)) {
7869*0fca6ea1SDimitry Andric           // Add the non-zero offset information into the load or store
7870*0fca6ea1SDimitry Andric           // instruction to be used for non-TOC-based local-[exec|dynamic]
7871*0fca6ea1SDimitry Andric           // accesses.
7872*0fca6ea1SDimitry Andric           GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd);
7873*0fca6ea1SDimitry Andric           assert(GA && "Expecting a valid GlobalAddressSDNode when folding "
7874*0fca6ea1SDimitry Andric                        "addi into local-[exec|dynamic] accesses!");
7875*0fca6ea1SDimitry Andric           ImmOpnd = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(GA),
7876*0fca6ea1SDimitry Andric                                                    MVT::i64, Offset,
7877*0fca6ea1SDimitry Andric                                                    GA->getTargetFlags());
7878*0fca6ea1SDimitry Andric         } else
78790b57cec5SDimitry Andric           continue;
78800b57cec5SDimitry Andric       }
78810b57cec5SDimitry Andric     }
78820b57cec5SDimitry Andric 
78830b57cec5SDimitry Andric     // We found an opportunity.  Reverse the operands from the add
78840b57cec5SDimitry Andric     // immediate and substitute them into the load or store.  If
78850b57cec5SDimitry Andric     // needed, update the target flags for the immediate operand to
78860b57cec5SDimitry Andric     // reflect the necessary relocation information.
78870b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase:    ");
78880b57cec5SDimitry Andric     LLVM_DEBUG(Base->dump(CurDAG));
78890b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\nN: ");
78900b57cec5SDimitry Andric     LLVM_DEBUG(N->dump(CurDAG));
78910b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\n");
78920b57cec5SDimitry Andric 
78930b57cec5SDimitry Andric     // If the relocation information isn't already present on the
78940b57cec5SDimitry Andric     // immediate operand, add it now.
78950b57cec5SDimitry Andric     if (ReplaceFlags) {
78960b57cec5SDimitry Andric       if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
78970b57cec5SDimitry Andric         SDLoc dl(GA);
78980b57cec5SDimitry Andric         const GlobalValue *GV = GA->getGlobal();
78995ffd83dbSDimitry Andric         Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout());
79000b57cec5SDimitry Andric         // We can't perform this optimization for data whose alignment
79010b57cec5SDimitry Andric         // is insufficient for the instruction encoding.
79025ffd83dbSDimitry Andric         if (Alignment < 4 && (RequiresMod4Offset || (Offset % 4) != 0)) {
79030b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "Rejected this candidate for alignment.\n\n");
79040b57cec5SDimitry Andric           continue;
79050b57cec5SDimitry Andric         }
79060b57cec5SDimitry Andric         ImmOpnd = CurDAG->getTargetGlobalAddress(GV, dl, MVT::i64, Offset, Flags);
79070b57cec5SDimitry Andric       } else if (ConstantPoolSDNode *CP =
79080b57cec5SDimitry Andric                  dyn_cast<ConstantPoolSDNode>(ImmOpnd)) {
79090b57cec5SDimitry Andric         const Constant *C = CP->getConstVal();
79105ffd83dbSDimitry Andric         ImmOpnd = CurDAG->getTargetConstantPool(C, MVT::i64, CP->getAlign(),
79110b57cec5SDimitry Andric                                                 Offset, Flags);
79120b57cec5SDimitry Andric       }
79130b57cec5SDimitry Andric     }
79140b57cec5SDimitry Andric 
79150b57cec5SDimitry Andric     if (FirstOp == 1) // Store
79160b57cec5SDimitry Andric       (void)CurDAG->UpdateNodeOperands(N, N->getOperand(0), ImmOpnd,
79170b57cec5SDimitry Andric                                        Base.getOperand(0), N->getOperand(3));
79180b57cec5SDimitry Andric     else // Load
79190b57cec5SDimitry Andric       (void)CurDAG->UpdateNodeOperands(N, ImmOpnd, Base.getOperand(0),
79200b57cec5SDimitry Andric                                        N->getOperand(2));
79210b57cec5SDimitry Andric 
79220b57cec5SDimitry Andric     if (UpdateHBase)
79230b57cec5SDimitry Andric       (void)CurDAG->UpdateNodeOperands(HBase.getNode(), HBase.getOperand(0),
79240b57cec5SDimitry Andric                                        ImmOpnd);
79250b57cec5SDimitry Andric 
79260b57cec5SDimitry Andric     // The add-immediate may now be dead, in which case remove it.
79270b57cec5SDimitry Andric     if (Base.getNode()->use_empty())
79280b57cec5SDimitry Andric       CurDAG->RemoveDeadNode(Base.getNode());
79290b57cec5SDimitry Andric   }
79300b57cec5SDimitry Andric }
79310b57cec5SDimitry Andric 
79320b57cec5SDimitry Andric /// createPPCISelDag - This pass converts a legalized DAG into a
79330b57cec5SDimitry Andric /// PowerPC-specific DAG, ready for instruction scheduling.
79340b57cec5SDimitry Andric ///
createPPCISelDag(PPCTargetMachine & TM,CodeGenOptLevel OptLevel)79350b57cec5SDimitry Andric FunctionPass *llvm::createPPCISelDag(PPCTargetMachine &TM,
79365f757f3fSDimitry Andric                                      CodeGenOptLevel OptLevel) {
7937*0fca6ea1SDimitry Andric   return new PPCDAGToDAGISelLegacy(TM, OptLevel);
79380b57cec5SDimitry Andric }
7939