1//===-- SILowerI1Copies.h --------------------------------------*- C++ -*--===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// Interface definition of the PhiLoweringHelper class that implements lane
11/// mask merging algorithm for divergent i1 phis.
12//
13//===----------------------------------------------------------------------===//
14
15#include "GCNSubtarget.h"
16#include "llvm/CodeGen/MachineBasicBlock.h"
17#include "llvm/CodeGen/MachinePostDominators.h"
18#include "llvm/CodeGen/MachineSSAUpdater.h"
19
20namespace llvm {
21
22/// Incoming for lane maks phi as machine instruction, incoming register \p Reg
23/// and incoming block \p Block are taken from machine instruction.
24/// \p UpdatedReg (if valid) is \p Reg lane mask merged with another lane mask.
25struct Incoming {
26  Register Reg;
27  MachineBasicBlock *Block;
28  Register UpdatedReg;
29
30  Incoming(Register Reg, MachineBasicBlock *Block, Register UpdatedReg)
31      : Reg(Reg), Block(Block), UpdatedReg(UpdatedReg) {}
32};
33
34Register createLaneMaskReg(MachineRegisterInfo *MRI, Register LaneMaskRegAttrs);
35
36class PhiLoweringHelper {
37public:
38  PhiLoweringHelper(MachineFunction *MF, MachineDominatorTree *DT,
39                    MachinePostDominatorTree *PDT);
40  virtual ~PhiLoweringHelper() = default;
41
42protected:
43  bool IsWave32 = false;
44  MachineFunction *MF = nullptr;
45  MachineDominatorTree *DT = nullptr;
46  MachinePostDominatorTree *PDT = nullptr;
47  MachineRegisterInfo *MRI = nullptr;
48  const GCNSubtarget *ST = nullptr;
49  const SIInstrInfo *TII = nullptr;
50  Register LaneMaskRegAttrs;
51
52#ifndef NDEBUG
53  DenseSet<Register> PhiRegisters;
54#endif
55
56  Register ExecReg;
57  unsigned MovOp;
58  unsigned AndOp;
59  unsigned OrOp;
60  unsigned XorOp;
61  unsigned AndN2Op;
62  unsigned OrN2Op;
63
64public:
65  bool lowerPhis();
66  bool isConstantLaneMask(Register Reg, bool &Val) const;
67  MachineBasicBlock::iterator
68  getSaluInsertionAtEnd(MachineBasicBlock &MBB) const;
69
70  void initializeLaneMaskRegisterAttributes(Register LaneMask) {
71    LaneMaskRegAttrs = LaneMask;
72  }
73
74  bool isLaneMaskReg(Register Reg) const {
75    return TII->getRegisterInfo().isSGPRReg(*MRI, Reg) &&
76           TII->getRegisterInfo().getRegSizeInBits(Reg, *MRI) ==
77               ST->getWavefrontSize();
78  }
79
80  // Helpers from lowerPhis that are different between sdag and global-isel.
81
82  virtual void markAsLaneMask(Register DstReg) const = 0;
83  virtual void getCandidatesForLowering(
84      SmallVectorImpl<MachineInstr *> &Vreg1Phis) const = 0;
85  virtual void
86  collectIncomingValuesFromPhi(const MachineInstr *MI,
87                               SmallVectorImpl<Incoming> &Incomings) const = 0;
88  virtual void replaceDstReg(Register NewReg, Register OldReg,
89                             MachineBasicBlock *MBB) = 0;
90  virtual void buildMergeLaneMasks(MachineBasicBlock &MBB,
91                                   MachineBasicBlock::iterator I,
92                                   const DebugLoc &DL, Register DstReg,
93                                   Register PrevReg, Register CurReg) = 0;
94  virtual void constrainIncomingRegisterTakenAsIs(Incoming &In) = 0;
95};
96
97} // end namespace llvm
98