Bug Summary

File:build/source/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
Warning:line 85, column 12
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name GCNVOPDUtils.cpp -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Target/AMDGPU -I /build/source/llvm/lib/Target/AMDGPU -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1668078801 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-11-10-135928-647445-1 -x c++ /build/source/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
1//===- GCNVOPDUtils.cpp - GCN VOPD Utils ------------------------===//
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 This file contains the AMDGPU DAG scheduling
10/// mutation to pair VOPD instructions back to back. It also contains
11// subroutines useful in the creation of VOPD instructions
12//
13//===----------------------------------------------------------------------===//
14
15#include "GCNVOPDUtils.h"
16#include "AMDGPUSubtarget.h"
17#include "GCNSubtarget.h"
18#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
19#include "SIInstrInfo.h"
20#include "Utils/AMDGPUBaseInfo.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/CodeGen/MachineBasicBlock.h"
24#include "llvm/CodeGen/MachineInstr.h"
25#include "llvm/CodeGen/MachineOperand.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
27#include "llvm/CodeGen/MacroFusion.h"
28#include "llvm/CodeGen/ScheduleDAG.h"
29#include "llvm/CodeGen/ScheduleDAGMutation.h"
30#include "llvm/CodeGen/TargetInstrInfo.h"
31#include "llvm/MC/MCInst.h"
32
33using namespace llvm;
34
35#define DEBUG_TYPE"gcn-vopd-utils" "gcn-vopd-utils"
36
37bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
38 const MachineInstr &FirstMI,
39 const MachineInstr &SecondMI) {
40 namespace VOPD = AMDGPU::VOPD;
41
42 const MachineFunction *MF = FirstMI.getMF();
43 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
44 const SIRegisterInfo *TRI = dyn_cast<SIRegisterInfo>(ST.getRegisterInfo());
1
Assuming the object is not a 'CastReturnType'
2
'TRI' initialized to a null pointer value
45 const MachineRegisterInfo &MRI = MF->getRegInfo();
46 // Literals also count against scalar bus limit
47 SmallVector<const MachineOperand *> UniqueLiterals;
48 auto addLiteral = [&](const MachineOperand &Op) {
49 for (auto &Literal : UniqueLiterals) {
50 if (Literal->isIdenticalTo(Op))
51 return;
52 }
53 UniqueLiterals.push_back(&Op);
54 };
55 SmallVector<Register> UniqueScalarRegs;
56 assert([&]() -> bool {(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
3
Assuming the condition is true
4
'?' condition is true
57 for (auto MII = MachineBasicBlock::const_iterator(&FirstMI);(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
58 MII != FirstMI.getParent()->instr_end(); ++MII) {(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
59 if (&*MII == &SecondMI)(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
60 return true;(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
61 }(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
62 return false;(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
63 }() && "Expected FirstMI to precede SecondMI")(static_cast <bool> ([&]() -> bool { for (auto MII
= MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI
.getParent()->instr_end(); ++MII) { if (&*MII == &
SecondMI) return true; } return false; }() && "Expected FirstMI to precede SecondMI"
) ? void (0) : __assert_fail ("[&]() -> bool { for (auto MII = MachineBasicBlock::const_iterator(&FirstMI); MII != FirstMI.getParent()->instr_end(); ++MII) { if (&*MII == &SecondMI) return true; } return false; }() && \"Expected FirstMI to precede SecondMI\""
, "llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp", 63, __extension__
__PRETTY_FUNCTION__))
;
64 // Cannot pair dependent instructions
65 for (const auto &Use : SecondMI.uses())
5
Assuming '__begin1' is equal to '__end1'
66 if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg()))
67 return false;
68
69 auto getVRegIdx = [&](unsigned OpcodeIdx, unsigned OperandIdx) {
70 const MachineInstr &MI = (OpcodeIdx == VOPD::X) ? FirstMI : SecondMI;
71 const MachineOperand &Operand = MI.getOperand(OperandIdx);
72 if (Operand.isReg() && TRI->isVectorRegister(MRI, Operand.getReg()))
73 return Operand.getReg();
74 return Register();
75 };
76
77 auto InstInfo =
78 AMDGPU::getVOPDInstInfo(FirstMI.getDesc(), SecondMI.getDesc());
79
80 for (auto CompIdx : VOPD::COMPONENTS) {
81 const MachineInstr &MI = (CompIdx
5.1
'CompIdx' is equal to X
== VOPD::X) ? FirstMI : SecondMI;
6
'?' condition is true
82
83 const MachineOperand &Src0 = MI.getOperand(VOPD::Component::SRC0);
84 if (Src0.isReg()) {
7
Taking true branch
85 if (!TRI->isVectorRegister(MRI, Src0.getReg())) {
8
Called C++ object pointer is null
86 if (!is_contained(UniqueScalarRegs, Src0.getReg()))
87 UniqueScalarRegs.push_back(Src0.getReg());
88 }
89 } else {
90 if (!TII.isInlineConstant(MI, VOPD::Component::SRC0))
91 addLiteral(Src0);
92 }
93
94 if (InstInfo[CompIdx].hasMandatoryLiteral())
95 addLiteral(MI.getOperand(InstInfo[CompIdx].getMandatoryLiteralIndex()));
96 if (MI.getDesc().hasImplicitUseOfPhysReg(AMDGPU::VCC))
97 UniqueScalarRegs.push_back(AMDGPU::VCC_LO);
98 }
99
100 if (UniqueLiterals.size() > 1)
101 return false;
102 if ((UniqueLiterals.size() + UniqueScalarRegs.size()) > 2)
103 return false;
104 if (InstInfo.hasInvalidOperand(getVRegIdx))
105 return false;
106
107 LLVM_DEBUG(dbgs() << "VOPD Reg Constraints Passed\n\tX: " << FirstMIdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("gcn-vopd-utils")) { dbgs() << "VOPD Reg Constraints Passed\n\tX: "
<< FirstMI << "\n\tY: " << SecondMI <<
"\n"; } } while (false)
108 << "\n\tY: " << SecondMI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("gcn-vopd-utils")) { dbgs() << "VOPD Reg Constraints Passed\n\tX: "
<< FirstMI << "\n\tY: " << SecondMI <<
"\n"; } } while (false)
;
109 return true;
110}
111
112/// Check if the instr pair, FirstMI and SecondMI, should be scheduled
113/// together. Given SecondMI, when FirstMI is unspecified, then check if
114/// SecondMI may be part of a fused pair at all.
115static bool shouldScheduleVOPDAdjacent(const TargetInstrInfo &TII,
116 const TargetSubtargetInfo &TSI,
117 const MachineInstr *FirstMI,
118 const MachineInstr &SecondMI) {
119 const SIInstrInfo &STII = static_cast<const SIInstrInfo &>(TII);
120 unsigned Opc2 = SecondMI.getOpcode();
121 auto SecondCanBeVOPD = AMDGPU::getCanBeVOPD(Opc2);
122
123 // One instruction case
124 if (!FirstMI)
125 return SecondCanBeVOPD.Y;
126
127 unsigned Opc = FirstMI->getOpcode();
128 auto FirstCanBeVOPD = AMDGPU::getCanBeVOPD(Opc);
129
130 if (!((FirstCanBeVOPD.X && SecondCanBeVOPD.Y) ||
131 (FirstCanBeVOPD.Y && SecondCanBeVOPD.X)))
132 return false;
133
134 return checkVOPDRegConstraints(STII, *FirstMI, SecondMI);
135}
136
137/// Adapts design from MacroFusion
138/// Puts valid candidate instructions back-to-back so they can easily
139/// be turned into VOPD instructions
140/// Greedily pairs instruction candidates. O(n^2) algorithm.
141struct VOPDPairingMutation : ScheduleDAGMutation {
142 ShouldSchedulePredTy shouldScheduleAdjacent; // NOLINT: function pointer
143
144 VOPDPairingMutation(
145 ShouldSchedulePredTy shouldScheduleAdjacent) // NOLINT: function pointer
146 : shouldScheduleAdjacent(shouldScheduleAdjacent) {}
147
148 void apply(ScheduleDAGInstrs *DAG) override {
149 const TargetInstrInfo &TII = *DAG->TII;
150 const GCNSubtarget &ST = DAG->MF.getSubtarget<GCNSubtarget>();
151 if (!AMDGPU::hasVOPD(ST) || !ST.isWave32()) {
152 LLVM_DEBUG(dbgs() << "Target does not support VOPDPairingMutation\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("gcn-vopd-utils")) { dbgs() << "Target does not support VOPDPairingMutation\n"
; } } while (false)
;
153 return;
154 }
155
156 std::vector<SUnit>::iterator ISUI, JSUI;
157 for (ISUI = DAG->SUnits.begin(); ISUI != DAG->SUnits.end(); ++ISUI) {
158 const MachineInstr *IMI = ISUI->getInstr();
159 if (!shouldScheduleAdjacent(TII, ST, nullptr, *IMI))
160 continue;
161 if (!hasLessThanNumFused(*ISUI, 2))
162 continue;
163
164 for (JSUI = ISUI + 1; JSUI != DAG->SUnits.end(); ++JSUI) {
165 if (JSUI->isBoundaryNode())
166 continue;
167 const MachineInstr *JMI = JSUI->getInstr();
168 if (!hasLessThanNumFused(*JSUI, 2) ||
169 !shouldScheduleAdjacent(TII, ST, IMI, *JMI))
170 continue;
171 if (fuseInstructionPair(*DAG, *ISUI, *JSUI))
172 break;
173 }
174 }
175 LLVM_DEBUG(dbgs() << "Completed VOPDPairingMutation\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("gcn-vopd-utils")) { dbgs() << "Completed VOPDPairingMutation\n"
; } } while (false)
;
176 }
177};
178
179std::unique_ptr<ScheduleDAGMutation> llvm::createVOPDPairingMutation() {
180 return std::make_unique<VOPDPairingMutation>(shouldScheduleVOPDAdjacent);
181}