Bug Summary

File:src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU/GCNMinRegStrategy.cpp
Warning:line 170, column 5
Value stored to 'Num' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name GCNMinRegStrategy.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU/GCNMinRegStrategy.cpp
1//===- GCNMinRegStrategy.cpp ----------------------------------------------===//
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/// This file defines and imlements the class GCNMinRegScheduler, which
11/// implements an experimental, simple scheduler whose main goal is to learn
12/// ways about consuming less possible registers for a region.
13///
14//===----------------------------------------------------------------------===//
15
16#include "llvm/CodeGen/ScheduleDAG.h"
17using namespace llvm;
18
19#define DEBUG_TYPE"machine-scheduler" "machine-scheduler"
20
21namespace {
22
23class GCNMinRegScheduler {
24 struct Candidate : ilist_node<Candidate> {
25 const SUnit *SU;
26 int Priority;
27
28 Candidate(const SUnit *SU_, int Priority_ = 0)
29 : SU(SU_), Priority(Priority_) {}
30 };
31
32 SpecificBumpPtrAllocator<Candidate> Alloc;
33 using Queue = simple_ilist<Candidate>;
34 Queue RQ; // Ready queue
35
36 std::vector<unsigned> NumPreds;
37
38 bool isScheduled(const SUnit *SU) const {
39 assert(!SU->isBoundaryNode())((void)0);
40 return NumPreds[SU->NodeNum] == std::numeric_limits<unsigned>::max();
41 }
42
43 void setIsScheduled(const SUnit *SU) {
44 assert(!SU->isBoundaryNode())((void)0);
45 NumPreds[SU->NodeNum] = std::numeric_limits<unsigned>::max();
46 }
47
48 unsigned getNumPreds(const SUnit *SU) const {
49 assert(!SU->isBoundaryNode())((void)0);
50 assert(NumPreds[SU->NodeNum] != std::numeric_limits<unsigned>::max())((void)0);
51 return NumPreds[SU->NodeNum];
52 }
53
54 unsigned decNumPreds(const SUnit *SU) {
55 assert(!SU->isBoundaryNode())((void)0);
56 assert(NumPreds[SU->NodeNum] != std::numeric_limits<unsigned>::max())((void)0);
57 return --NumPreds[SU->NodeNum];
58 }
59
60 void initNumPreds(const decltype(ScheduleDAG::SUnits) &SUnits);
61
62 int getReadySuccessors(const SUnit *SU) const;
63 int getNotReadySuccessors(const SUnit *SU) const;
64
65 template <typename Calc>
66 unsigned findMax(unsigned Num, Calc C);
67
68 Candidate* pickCandidate();
69
70 void bumpPredsPriority(const SUnit *SchedSU, int Priority);
71 void releaseSuccessors(const SUnit* SU, int Priority);
72
73public:
74 std::vector<const SUnit*> schedule(ArrayRef<const SUnit*> TopRoots,
75 const ScheduleDAG &DAG);
76};
77
78} // end anonymous namespace
79
80void GCNMinRegScheduler::initNumPreds(const decltype(ScheduleDAG::SUnits) &SUnits) {
81 NumPreds.resize(SUnits.size());
82 for (unsigned I = 0; I < SUnits.size(); ++I)
83 NumPreds[I] = SUnits[I].NumPredsLeft;
84}
85
86int GCNMinRegScheduler::getReadySuccessors(const SUnit *SU) const {
87 unsigned NumSchedSuccs = 0;
88 for (auto SDep : SU->Succs) {
89 bool wouldBeScheduled = true;
90 for (auto PDep : SDep.getSUnit()->Preds) {
91 auto PSU = PDep.getSUnit();
92 assert(!PSU->isBoundaryNode())((void)0);
93 if (PSU != SU && !isScheduled(PSU)) {
94 wouldBeScheduled = false;
95 break;
96 }
97 }
98 NumSchedSuccs += wouldBeScheduled ? 1 : 0;
99 }
100 return NumSchedSuccs;
101}
102
103int GCNMinRegScheduler::getNotReadySuccessors(const SUnit *SU) const {
104 return SU->Succs.size() - getReadySuccessors(SU);
105}
106
107template <typename Calc>
108unsigned GCNMinRegScheduler::findMax(unsigned Num, Calc C) {
109 assert(!RQ.empty() && Num <= RQ.size())((void)0);
110
111 using T = decltype(C(*RQ.begin())) ;
112
113 T Max = std::numeric_limits<T>::min();
114 unsigned NumMax = 0;
115 for (auto I = RQ.begin(); Num; --Num) {
116 T Cur = C(*I);
117 if (Cur >= Max) {
118 if (Cur > Max) {
119 Max = Cur;
120 NumMax = 1;
121 } else
122 ++NumMax;
123 auto &Cand = *I++;
124 RQ.remove(Cand);
125 RQ.push_front(Cand);
126 continue;
127 }
128 ++I;
129 }
130 return NumMax;
131}
132
133GCNMinRegScheduler::Candidate* GCNMinRegScheduler::pickCandidate() {
134 do {
135 unsigned Num = RQ.size();
136 if (Num == 1) break;
137
138 LLVM_DEBUG(dbgs() << "\nSelecting max priority candidates among " << Numdo { } while (false)
139 << '\n')do { } while (false);
140 Num = findMax(Num, [=](const Candidate &C) { return C.Priority; });
141 if (Num == 1) break;
142
143 LLVM_DEBUG(dbgs() << "\nSelecting min non-ready producing candidate among "do { } while (false)
144 << Num << '\n')do { } while (false);
145 Num = findMax(Num, [=](const Candidate &C) {
146 auto SU = C.SU;
147 int Res = getNotReadySuccessors(SU);
148 LLVM_DEBUG(dbgs() << "SU(" << SU->NodeNum << ") would left non-ready "do { } while (false)
149 << Res << " successors, metric = " << -Res << '\n')do { } while (false);
150 return -Res;
151 });
152 if (Num == 1) break;
153
154 LLVM_DEBUG(dbgs() << "\nSelecting most producing candidate among " << Numdo { } while (false)
155 << '\n')do { } while (false);
156 Num = findMax(Num, [=](const Candidate &C) {
157 auto SU = C.SU;
158 auto Res = getReadySuccessors(SU);
159 LLVM_DEBUG(dbgs() << "SU(" << SU->NodeNum << ") would make ready " << Resdo { } while (false)
160 << " successors, metric = " << Res << '\n')do { } while (false);
161 return Res;
162 });
163 if (Num == 1) break;
164
165 Num = Num ? Num : RQ.size();
166 LLVM_DEBUG(do { } while (false)
167 dbgs()do { } while (false)
168 << "\nCan't find best candidate, selecting in program order among "do { } while (false)
169 << Num << '\n')do { } while (false);
170 Num = findMax(Num, [=](const Candidate &C) { return -(int64_t)C.SU->NodeNum; });
Value stored to 'Num' is never read
171 assert(Num == 1)((void)0);
172 } while (false);
173
174 return &RQ.front();
175}
176
177void GCNMinRegScheduler::bumpPredsPriority(const SUnit *SchedSU, int Priority) {
178 SmallPtrSet<const SUnit*, 32> Set;
179 for (const auto &S : SchedSU->Succs) {
180 if (S.getSUnit()->isBoundaryNode() || isScheduled(S.getSUnit()) ||
181 S.getKind() != SDep::Data)
182 continue;
183 for (const auto &P : S.getSUnit()->Preds) {
184 auto PSU = P.getSUnit();
185 assert(!PSU->isBoundaryNode())((void)0);
186 if (PSU != SchedSU && !isScheduled(PSU)) {
187 Set.insert(PSU);
188 }
189 }
190 }
191 SmallVector<const SUnit*, 32> Worklist(Set.begin(), Set.end());
192 while (!Worklist.empty()) {
193 auto SU = Worklist.pop_back_val();
194 assert(!SU->isBoundaryNode())((void)0);
195 for (const auto &P : SU->Preds) {
196 if (!P.getSUnit()->isBoundaryNode() && !isScheduled(P.getSUnit()) &&
197 Set.insert(P.getSUnit()).second)
198 Worklist.push_back(P.getSUnit());
199 }
200 }
201 LLVM_DEBUG(dbgs() << "Make the predecessors of SU(" << SchedSU->NodeNumdo { } while (false)
202 << ")'s non-ready successors of " << Prioritydo { } while (false)
203 << " priority in ready queue: ")do { } while (false);
204 for (auto &C : RQ) {
205 if (Set.count(C.SU)) {
206 C.Priority = Priority;
207 LLVM_DEBUG(dbgs() << " SU(" << C.SU->NodeNum << ')')do { } while (false);
208 }
209 }
210 LLVM_DEBUG(dbgs() << '\n')do { } while (false);
211}
212
213void GCNMinRegScheduler::releaseSuccessors(const SUnit* SU, int Priority) {
214 for (const auto &S : SU->Succs) {
215 auto SuccSU = S.getSUnit();
216 if (S.isWeak())
217 continue;
218 assert(SuccSU->isBoundaryNode() || getNumPreds(SuccSU) > 0)((void)0);
219 if (!SuccSU->isBoundaryNode() && decNumPreds(SuccSU) == 0)
220 RQ.push_front(*new (Alloc.Allocate()) Candidate(SuccSU, Priority));
221 }
222}
223
224std::vector<const SUnit*>
225GCNMinRegScheduler::schedule(ArrayRef<const SUnit*> TopRoots,
226 const ScheduleDAG &DAG) {
227 const auto &SUnits = DAG.SUnits;
228 std::vector<const SUnit*> Schedule;
229 Schedule.reserve(SUnits.size());
230
231 initNumPreds(SUnits);
232
233 int StepNo = 0;
234
235 for (auto SU : TopRoots) {
236 RQ.push_back(*new (Alloc.Allocate()) Candidate(SU, StepNo));
237 }
238 releaseSuccessors(&DAG.EntrySU, StepNo);
239
240 while (!RQ.empty()) {
241 LLVM_DEBUG(dbgs() << "\n=== Picking candidate, Step = " << StepNodo { } while (false)
242 << "\n"do { } while (false)
243 "Ready queue:";do { } while (false)
244 for (auto &Cdo { } while (false)
245 : RQ) dbgs()do { } while (false)
246 << ' ' << C.SU->NodeNum << "(P" << C.Priority << ')';do { } while (false)
247 dbgs() << '\n';)do { } while (false);
248
249 auto C = pickCandidate();
250 assert(C)((void)0);
251 RQ.remove(*C);
252 auto SU = C->SU;
253 LLVM_DEBUG(dbgs() << "Selected "; DAG.dumpNode(*SU))do { } while (false);
254
255 releaseSuccessors(SU, StepNo);
256 Schedule.push_back(SU);
257 setIsScheduled(SU);
258
259 if (getReadySuccessors(SU) == 0)
260 bumpPredsPriority(SU, StepNo);
261
262 ++StepNo;
263 }
264 assert(SUnits.size() == Schedule.size())((void)0);
265
266 return Schedule;
267}
268
269namespace llvm {
270
271std::vector<const SUnit*> makeMinRegSchedule(ArrayRef<const SUnit*> TopRoots,
272 const ScheduleDAG &DAG) {
273 GCNMinRegScheduler S;
274 return S.schedule(TopRoots, DAG);
275}
276
277} // end namespace llvm