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