1bdd1243dSDimitry Andric //===- MachineUniformityAnalysis.cpp --------------------------------------===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric
9bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineUniformityAnalysis.h"
10bdd1243dSDimitry Andric #include "llvm/ADT/GenericUniformityImpl.h"
11bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineCycleAnalysis.h"
12bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
13bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
14bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineSSAContext.h"
15bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
16bdd1243dSDimitry Andric #include "llvm/InitializePasses.h"
17bdd1243dSDimitry Andric
18bdd1243dSDimitry Andric using namespace llvm;
19bdd1243dSDimitry Andric
20bdd1243dSDimitry Andric template <>
hasDivergentDefs(const MachineInstr & I) const21bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::hasDivergentDefs(
22bdd1243dSDimitry Andric const MachineInstr &I) const {
2306c3fb27SDimitry Andric for (auto &op : I.all_defs()) {
24bdd1243dSDimitry Andric if (isDivergent(op.getReg()))
25bdd1243dSDimitry Andric return true;
26bdd1243dSDimitry Andric }
27bdd1243dSDimitry Andric return false;
28bdd1243dSDimitry Andric }
29bdd1243dSDimitry Andric
30bdd1243dSDimitry Andric template <>
markDefsDivergent(const MachineInstr & Instr)31bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::markDefsDivergent(
3206c3fb27SDimitry Andric const MachineInstr &Instr) {
33bdd1243dSDimitry Andric bool insertedDivergent = false;
34bdd1243dSDimitry Andric const auto &MRI = F.getRegInfo();
3506c3fb27SDimitry Andric const auto &RBI = *F.getSubtarget().getRegBankInfo();
36bdd1243dSDimitry Andric const auto &TRI = *MRI.getTargetRegisterInfo();
3706c3fb27SDimitry Andric for (auto &op : Instr.all_defs()) {
38bdd1243dSDimitry Andric if (!op.getReg().isVirtual())
39bdd1243dSDimitry Andric continue;
40bdd1243dSDimitry Andric assert(!op.getSubReg());
4106c3fb27SDimitry Andric if (TRI.isUniformReg(MRI, RBI, op.getReg()))
42bdd1243dSDimitry Andric continue;
43bdd1243dSDimitry Andric insertedDivergent |= markDivergent(op.getReg());
44bdd1243dSDimitry Andric }
45bdd1243dSDimitry Andric return insertedDivergent;
46bdd1243dSDimitry Andric }
47bdd1243dSDimitry Andric
48bdd1243dSDimitry Andric template <>
initialize()49bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
50bdd1243dSDimitry Andric const auto &InstrInfo = *F.getSubtarget().getInstrInfo();
51bdd1243dSDimitry Andric
52bdd1243dSDimitry Andric for (const MachineBasicBlock &block : F) {
53bdd1243dSDimitry Andric for (const MachineInstr &instr : block) {
54bdd1243dSDimitry Andric auto uniformity = InstrInfo.getInstructionUniformity(instr);
55bdd1243dSDimitry Andric if (uniformity == InstructionUniformity::AlwaysUniform) {
56bdd1243dSDimitry Andric addUniformOverride(instr);
57bdd1243dSDimitry Andric continue;
58bdd1243dSDimitry Andric }
59bdd1243dSDimitry Andric
60bdd1243dSDimitry Andric if (uniformity == InstructionUniformity::NeverUniform) {
6106c3fb27SDimitry Andric markDivergent(instr);
62bdd1243dSDimitry Andric }
63bdd1243dSDimitry Andric }
64bdd1243dSDimitry Andric }
65bdd1243dSDimitry Andric }
66bdd1243dSDimitry Andric
67bdd1243dSDimitry Andric template <>
pushUsers(Register Reg)68bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
69bdd1243dSDimitry Andric Register Reg) {
7006c3fb27SDimitry Andric assert(isDivergent(Reg));
71bdd1243dSDimitry Andric const auto &RegInfo = F.getRegInfo();
72bdd1243dSDimitry Andric for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) {
7306c3fb27SDimitry Andric markDivergent(UserInstr);
74bdd1243dSDimitry Andric }
75bdd1243dSDimitry Andric }
76bdd1243dSDimitry Andric
77bdd1243dSDimitry Andric template <>
pushUsers(const MachineInstr & Instr)78bdd1243dSDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
79bdd1243dSDimitry Andric const MachineInstr &Instr) {
80bdd1243dSDimitry Andric assert(!isAlwaysUniform(Instr));
81bdd1243dSDimitry Andric if (Instr.isTerminator())
82bdd1243dSDimitry Andric return;
8306c3fb27SDimitry Andric for (const MachineOperand &op : Instr.all_defs()) {
8406c3fb27SDimitry Andric auto Reg = op.getReg();
8506c3fb27SDimitry Andric if (isDivergent(Reg))
8606c3fb27SDimitry Andric pushUsers(Reg);
87bdd1243dSDimitry Andric }
88bdd1243dSDimitry Andric }
89bdd1243dSDimitry Andric
90bdd1243dSDimitry Andric template <>
usesValueFromCycle(const MachineInstr & I,const MachineCycle & DefCycle) const91bdd1243dSDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::usesValueFromCycle(
92bdd1243dSDimitry Andric const MachineInstr &I, const MachineCycle &DefCycle) const {
93bdd1243dSDimitry Andric assert(!isAlwaysUniform(I));
94bdd1243dSDimitry Andric for (auto &Op : I.operands()) {
95bdd1243dSDimitry Andric if (!Op.isReg() || !Op.readsReg())
96bdd1243dSDimitry Andric continue;
97bdd1243dSDimitry Andric auto Reg = Op.getReg();
9806c3fb27SDimitry Andric
9906c3fb27SDimitry Andric // FIXME: Physical registers need to be properly checked instead of always
10006c3fb27SDimitry Andric // returning true
10106c3fb27SDimitry Andric if (Reg.isPhysical())
10206c3fb27SDimitry Andric return true;
10306c3fb27SDimitry Andric
104bdd1243dSDimitry Andric auto *Def = F.getRegInfo().getVRegDef(Reg);
105bdd1243dSDimitry Andric if (DefCycle.contains(Def->getParent()))
106bdd1243dSDimitry Andric return true;
107bdd1243dSDimitry Andric }
108bdd1243dSDimitry Andric return false;
109bdd1243dSDimitry Andric }
110bdd1243dSDimitry Andric
11106c3fb27SDimitry Andric template <>
11206c3fb27SDimitry Andric void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::
propagateTemporalDivergence(const MachineInstr & I,const MachineCycle & DefCycle)11306c3fb27SDimitry Andric propagateTemporalDivergence(const MachineInstr &I,
11406c3fb27SDimitry Andric const MachineCycle &DefCycle) {
11506c3fb27SDimitry Andric const auto &RegInfo = F.getRegInfo();
11606c3fb27SDimitry Andric for (auto &Op : I.all_defs()) {
11706c3fb27SDimitry Andric if (!Op.getReg().isVirtual())
11806c3fb27SDimitry Andric continue;
11906c3fb27SDimitry Andric auto Reg = Op.getReg();
12006c3fb27SDimitry Andric if (isDivergent(Reg))
12106c3fb27SDimitry Andric continue;
12206c3fb27SDimitry Andric for (MachineInstr &UserInstr : RegInfo.use_instructions(Reg)) {
12306c3fb27SDimitry Andric if (DefCycle.contains(UserInstr.getParent()))
12406c3fb27SDimitry Andric continue;
12506c3fb27SDimitry Andric markDivergent(UserInstr);
12606c3fb27SDimitry Andric }
12706c3fb27SDimitry Andric }
12806c3fb27SDimitry Andric }
12906c3fb27SDimitry Andric
13006c3fb27SDimitry Andric template <>
isDivergentUse(const MachineOperand & U) const13106c3fb27SDimitry Andric bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::isDivergentUse(
13206c3fb27SDimitry Andric const MachineOperand &U) const {
13306c3fb27SDimitry Andric if (!U.isReg())
13406c3fb27SDimitry Andric return false;
13506c3fb27SDimitry Andric
13606c3fb27SDimitry Andric auto Reg = U.getReg();
13706c3fb27SDimitry Andric if (isDivergent(Reg))
13806c3fb27SDimitry Andric return true;
13906c3fb27SDimitry Andric
14006c3fb27SDimitry Andric const auto &RegInfo = F.getRegInfo();
14106c3fb27SDimitry Andric auto *Def = RegInfo.getOneDef(Reg);
14206c3fb27SDimitry Andric if (!Def)
14306c3fb27SDimitry Andric return true;
14406c3fb27SDimitry Andric
14506c3fb27SDimitry Andric auto *DefInstr = Def->getParent();
14606c3fb27SDimitry Andric auto *UseInstr = U.getParent();
14706c3fb27SDimitry Andric return isTemporalDivergent(*UseInstr->getParent(), *DefInstr);
14806c3fb27SDimitry Andric }
14906c3fb27SDimitry Andric
150bdd1243dSDimitry Andric // This ensures explicit instantiation of
151bdd1243dSDimitry Andric // GenericUniformityAnalysisImpl::ImplDeleter::operator()
152bdd1243dSDimitry Andric template class llvm::GenericUniformityInfo<MachineSSAContext>;
153bdd1243dSDimitry Andric template struct llvm::GenericUniformityAnalysisImplDeleter<
154bdd1243dSDimitry Andric llvm::GenericUniformityAnalysisImpl<MachineSSAContext>>;
155bdd1243dSDimitry Andric
computeMachineUniformityInfo(MachineFunction & F,const MachineCycleInfo & cycleInfo,const MachineDominatorTree & domTree,bool HasBranchDivergence)15606c3fb27SDimitry Andric MachineUniformityInfo llvm::computeMachineUniformityInfo(
15706c3fb27SDimitry Andric MachineFunction &F, const MachineCycleInfo &cycleInfo,
158*0fca6ea1SDimitry Andric const MachineDominatorTree &domTree, bool HasBranchDivergence) {
159bdd1243dSDimitry Andric assert(F.getRegInfo().isSSA() && "Expected to be run on SSA form!");
1605f757f3fSDimitry Andric MachineUniformityInfo UI(domTree, cycleInfo);
16106c3fb27SDimitry Andric if (HasBranchDivergence)
16206c3fb27SDimitry Andric UI.compute();
16306c3fb27SDimitry Andric return UI;
164bdd1243dSDimitry Andric }
165bdd1243dSDimitry Andric
166bdd1243dSDimitry Andric namespace {
167bdd1243dSDimitry Andric
168bdd1243dSDimitry Andric class MachineUniformityInfoPrinterPass : public MachineFunctionPass {
169bdd1243dSDimitry Andric public:
170bdd1243dSDimitry Andric static char ID;
171bdd1243dSDimitry Andric
172bdd1243dSDimitry Andric MachineUniformityInfoPrinterPass();
173bdd1243dSDimitry Andric
174bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &F) override;
175bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override;
176bdd1243dSDimitry Andric };
177bdd1243dSDimitry Andric
178bdd1243dSDimitry Andric } // namespace
179bdd1243dSDimitry Andric
180bdd1243dSDimitry Andric char MachineUniformityAnalysisPass::ID = 0;
181bdd1243dSDimitry Andric
MachineUniformityAnalysisPass()182bdd1243dSDimitry Andric MachineUniformityAnalysisPass::MachineUniformityAnalysisPass()
183bdd1243dSDimitry Andric : MachineFunctionPass(ID) {
184bdd1243dSDimitry Andric initializeMachineUniformityAnalysisPassPass(*PassRegistry::getPassRegistry());
185bdd1243dSDimitry Andric }
186bdd1243dSDimitry Andric
187bdd1243dSDimitry Andric INITIALIZE_PASS_BEGIN(MachineUniformityAnalysisPass, "machine-uniformity",
188bdd1243dSDimitry Andric "Machine Uniformity Info Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)189bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)
190*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
191bdd1243dSDimitry Andric INITIALIZE_PASS_END(MachineUniformityAnalysisPass, "machine-uniformity",
192bdd1243dSDimitry Andric "Machine Uniformity Info Analysis", true, true)
193bdd1243dSDimitry Andric
194bdd1243dSDimitry Andric void MachineUniformityAnalysisPass::getAnalysisUsage(AnalysisUsage &AU) const {
195bdd1243dSDimitry Andric AU.setPreservesAll();
196bdd1243dSDimitry Andric AU.addRequired<MachineCycleInfoWrapperPass>();
197*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>();
198bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
199bdd1243dSDimitry Andric }
200bdd1243dSDimitry Andric
runOnMachineFunction(MachineFunction & MF)201bdd1243dSDimitry Andric bool MachineUniformityAnalysisPass::runOnMachineFunction(MachineFunction &MF) {
202*0fca6ea1SDimitry Andric auto &DomTree =
203*0fca6ea1SDimitry Andric getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree().getBase();
204bdd1243dSDimitry Andric auto &CI = getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo();
20506c3fb27SDimitry Andric // FIXME: Query TTI::hasBranchDivergence. -run-pass seems to end up with a
20606c3fb27SDimitry Andric // default NoTTI
20706c3fb27SDimitry Andric UI = computeMachineUniformityInfo(MF, CI, DomTree, true);
208bdd1243dSDimitry Andric return false;
209bdd1243dSDimitry Andric }
210bdd1243dSDimitry Andric
print(raw_ostream & OS,const Module *) const211bdd1243dSDimitry Andric void MachineUniformityAnalysisPass::print(raw_ostream &OS,
212bdd1243dSDimitry Andric const Module *) const {
213bdd1243dSDimitry Andric OS << "MachineUniformityInfo for function: " << UI.getFunction().getName()
214bdd1243dSDimitry Andric << "\n";
215bdd1243dSDimitry Andric UI.print(OS);
216bdd1243dSDimitry Andric }
217bdd1243dSDimitry Andric
218bdd1243dSDimitry Andric char MachineUniformityInfoPrinterPass::ID = 0;
219bdd1243dSDimitry Andric
MachineUniformityInfoPrinterPass()220bdd1243dSDimitry Andric MachineUniformityInfoPrinterPass::MachineUniformityInfoPrinterPass()
221bdd1243dSDimitry Andric : MachineFunctionPass(ID) {
222bdd1243dSDimitry Andric initializeMachineUniformityInfoPrinterPassPass(
223bdd1243dSDimitry Andric *PassRegistry::getPassRegistry());
224bdd1243dSDimitry Andric }
225bdd1243dSDimitry Andric
226bdd1243dSDimitry Andric INITIALIZE_PASS_BEGIN(MachineUniformityInfoPrinterPass,
227bdd1243dSDimitry Andric "print-machine-uniformity",
228bdd1243dSDimitry Andric "Print Machine Uniformity Info Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(MachineUniformityAnalysisPass)229bdd1243dSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineUniformityAnalysisPass)
230bdd1243dSDimitry Andric INITIALIZE_PASS_END(MachineUniformityInfoPrinterPass,
231bdd1243dSDimitry Andric "print-machine-uniformity",
232bdd1243dSDimitry Andric "Print Machine Uniformity Info Analysis", true, true)
233bdd1243dSDimitry Andric
234bdd1243dSDimitry Andric void MachineUniformityInfoPrinterPass::getAnalysisUsage(
235bdd1243dSDimitry Andric AnalysisUsage &AU) const {
236bdd1243dSDimitry Andric AU.setPreservesAll();
237bdd1243dSDimitry Andric AU.addRequired<MachineUniformityAnalysisPass>();
238bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
239bdd1243dSDimitry Andric }
240bdd1243dSDimitry Andric
runOnMachineFunction(MachineFunction & F)241bdd1243dSDimitry Andric bool MachineUniformityInfoPrinterPass::runOnMachineFunction(
242bdd1243dSDimitry Andric MachineFunction &F) {
243bdd1243dSDimitry Andric auto &UI = getAnalysis<MachineUniformityAnalysisPass>();
244bdd1243dSDimitry Andric UI.print(errs());
245bdd1243dSDimitry Andric return false;
246bdd1243dSDimitry Andric }
247