2011-09-14 16:47:44 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright 2011 Christoph Bumiller
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
2013-04-21 13:46:48 -07:00
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
2011-09-14 16:47:44 +02:00
|
|
|
*/
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2022-05-28 13:19:21 +10:00
|
|
|
#include "nv50_ir.h"
|
|
|
|
|
#include "nv50_ir_target.h"
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2015-12-06 23:25:54 -05:00
|
|
|
#include <algorithm>
|
2012-04-09 20:58:39 +02:00
|
|
|
#include <stack>
|
|
|
|
|
#include <limits>
|
2015-10-15 23:46:30 +08:00
|
|
|
#include <unordered_map>
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
namespace nv50_ir {
|
2023-08-19 12:22:07 -04:00
|
|
|
namespace {
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
#define MAX_REGISTER_FILE_SIZE 256
|
|
|
|
|
|
|
|
|
|
class RegisterSet
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
RegisterSet(const Target *);
|
|
|
|
|
|
|
|
|
|
void init(const Target *);
|
2012-04-09 20:58:39 +02:00
|
|
|
void reset(DataFile, bool resetMax = false);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2018-11-11 15:52:33 -05:00
|
|
|
bool assign(int32_t& reg, DataFile f, unsigned int size, unsigned int maxReg);
|
2013-02-06 17:14:55 +01:00
|
|
|
void occupy(DataFile f, int32_t reg, unsigned int size);
|
2012-04-09 20:58:39 +02:00
|
|
|
void occupyMask(DataFile f, int32_t reg, uint8_t mask);
|
2013-02-06 17:14:55 +01:00
|
|
|
bool isOccupied(DataFile f, int32_t reg, unsigned int size) const;
|
|
|
|
|
bool testOccupy(DataFile f, int32_t reg, unsigned int size);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
inline int getMaxAssigned(DataFile f) const { return fill[f]; }
|
|
|
|
|
|
2018-11-11 10:55:55 -05:00
|
|
|
inline unsigned int getFileSize(DataFile f) const
|
2012-04-09 20:58:39 +02:00
|
|
|
{
|
|
|
|
|
return last[f] + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline unsigned int units(DataFile f, unsigned int size) const
|
|
|
|
|
{
|
|
|
|
|
return size >> unit[f];
|
|
|
|
|
}
|
|
|
|
|
// for regs of size >= 4, id is counted in 4-byte words (like nv50/c0 binary)
|
2012-04-30 15:12:15 +02:00
|
|
|
inline unsigned int idToBytes(const Value *v) const
|
2012-04-09 20:58:39 +02:00
|
|
|
{
|
|
|
|
|
return v->reg.data.id * MIN2(v->reg.size, 4);
|
|
|
|
|
}
|
2012-04-30 15:12:15 +02:00
|
|
|
inline unsigned int idToUnits(const Value *v) const
|
2012-04-09 20:58:39 +02:00
|
|
|
{
|
|
|
|
|
return units(v->reg.file, idToBytes(v));
|
|
|
|
|
}
|
|
|
|
|
inline int bytesToId(Value *v, unsigned int bytes) const
|
|
|
|
|
{
|
|
|
|
|
if (v->reg.size < 4)
|
|
|
|
|
return units(v->reg.file, bytes);
|
|
|
|
|
return bytes / 4;
|
|
|
|
|
}
|
|
|
|
|
inline int unitsToId(DataFile f, int u, uint8_t size) const
|
|
|
|
|
{
|
|
|
|
|
if (u < 0)
|
|
|
|
|
return -1;
|
|
|
|
|
return (size < 4) ? u : ((u << unit[f]) / 4);
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2016-05-31 00:33:19 -04:00
|
|
|
void print(DataFile f) const;
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2015-12-08 18:21:26 -05:00
|
|
|
const bool restrictedGPR16Range;
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
private:
|
2012-04-09 20:58:39 +02:00
|
|
|
BitSet bits[LAST_REGISTER_FILE + 1];
|
|
|
|
|
|
|
|
|
|
int unit[LAST_REGISTER_FILE + 1]; // log2 of allocation granularity
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
int last[LAST_REGISTER_FILE + 1];
|
|
|
|
|
int fill[LAST_REGISTER_FILE + 1];
|
2011-09-14 16:18:23 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void
|
2012-04-09 20:58:39 +02:00
|
|
|
RegisterSet::reset(DataFile f, bool resetMax)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
bits[f].fill(0);
|
|
|
|
|
if (resetMax)
|
|
|
|
|
fill[f] = -1;
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RegisterSet::init(const Target *targ)
|
|
|
|
|
{
|
2020-07-14 22:32:47 +02:00
|
|
|
for (unsigned int rf = 0; rf <= LAST_REGISTER_FILE; ++rf) {
|
2011-09-14 16:18:23 +02:00
|
|
|
DataFile f = static_cast<DataFile>(rf);
|
|
|
|
|
last[rf] = targ->getFileSize(f) - 1;
|
|
|
|
|
unit[rf] = targ->getFileUnit(f);
|
|
|
|
|
fill[rf] = -1;
|
|
|
|
|
assert(last[rf] < MAX_REGISTER_FILE_SIZE);
|
2012-04-09 20:58:39 +02:00
|
|
|
bits[rf].allocate(last[rf] + 1, true);
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RegisterSet::RegisterSet(const Target *targ)
|
2012-04-09 20:58:39 +02:00
|
|
|
: restrictedGPR16Range(targ->getChipset() < 0xc0)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
|
|
|
|
init(targ);
|
2012-04-09 20:58:39 +02:00
|
|
|
for (unsigned int i = 0; i <= LAST_REGISTER_FILE; ++i)
|
|
|
|
|
reset(static_cast<DataFile>(i));
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2016-05-31 00:33:19 -04:00
|
|
|
RegisterSet::print(DataFile f) const
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
|
|
|
|
INFO("GPR:");
|
2016-05-31 00:33:19 -04:00
|
|
|
bits[f].print();
|
2011-09-14 16:18:23 +02:00
|
|
|
INFO("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2018-11-11 15:52:33 -05:00
|
|
|
RegisterSet::assign(int32_t& reg, DataFile f, unsigned int size, unsigned int maxReg)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2018-11-11 15:52:33 -05:00
|
|
|
reg = bits[f].findFreeRange(size, maxReg);
|
2012-04-09 20:58:39 +02:00
|
|
|
if (reg < 0)
|
2011-09-14 16:18:23 +02:00
|
|
|
return false;
|
2012-04-09 20:58:39 +02:00
|
|
|
fill[f] = MAX2(fill[f], (int32_t)(reg + size - 1));
|
2011-09-14 16:18:23 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-29 23:23:53 +02:00
|
|
|
bool
|
2013-02-06 17:14:55 +01:00
|
|
|
RegisterSet::isOccupied(DataFile f, int32_t reg, unsigned int size) const
|
|
|
|
|
{
|
|
|
|
|
return bits[f].testRange(reg, size);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
RegisterSet::occupyMask(DataFile f, int32_t reg, uint8_t mask)
|
|
|
|
|
{
|
|
|
|
|
bits[f].setMask(reg & ~31, static_cast<uint32_t>(mask) << (reg % 32));
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2013-02-06 17:14:55 +01:00
|
|
|
void
|
|
|
|
|
RegisterSet::occupy(DataFile f, int32_t reg, unsigned int size)
|
2012-04-09 20:58:39 +02:00
|
|
|
{
|
|
|
|
|
bits[f].setRange(reg, size);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
INFO_DBG(0, REG_ALLOC, "reg occupy: %u[%i] %u\n", f, reg, size);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
fill[f] = MAX2(fill[f], (int32_t)(reg + size - 1));
|
2013-02-06 17:14:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
RegisterSet::testOccupy(DataFile f, int32_t reg, unsigned int size)
|
|
|
|
|
{
|
|
|
|
|
if (isOccupied(f, reg, size))
|
|
|
|
|
return false;
|
|
|
|
|
occupy(f, reg, size);
|
2012-03-29 23:23:53 +02:00
|
|
|
return true;
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class RegAlloc
|
|
|
|
|
{
|
|
|
|
|
public:
|
2021-01-18 18:20:21 -08:00
|
|
|
RegAlloc(Program *program) : prog(program), func(NULL), sequence(0) { }
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
bool exec();
|
|
|
|
|
bool execFunc();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
class PhiMovesPass : public Pass {
|
|
|
|
|
private:
|
|
|
|
|
virtual bool visit(BasicBlock *);
|
|
|
|
|
inline bool needNewElseBlock(BasicBlock *b, BasicBlock *p);
|
2015-09-10 01:54:30 -04:00
|
|
|
inline void splitEdges(BasicBlock *b);
|
2011-09-14 16:18:23 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class BuildIntervalsPass : public Pass {
|
|
|
|
|
private:
|
|
|
|
|
virtual bool visit(BasicBlock *);
|
|
|
|
|
void collectLiveValues(BasicBlock *);
|
|
|
|
|
void addLiveRange(Value *, const BasicBlock *, int end);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class InsertConstraintsPass : public Pass {
|
|
|
|
|
public:
|
2021-01-16 17:53:58 -08:00
|
|
|
InsertConstraintsPass() : targ(NULL) { }
|
2011-09-14 16:18:23 +02:00
|
|
|
bool exec(Function *func);
|
|
|
|
|
private:
|
|
|
|
|
virtual bool visit(BasicBlock *);
|
|
|
|
|
|
2018-04-09 22:19:35 -04:00
|
|
|
void insertConstraintMove(Instruction *, int s);
|
2011-09-14 16:18:23 +02:00
|
|
|
bool insertConstraintMoves();
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void condenseDefs(Instruction *);
|
2018-08-05 20:41:49 +02:00
|
|
|
void condenseDefs(Instruction *, const int first, const int last);
|
2012-04-09 20:58:39 +02:00
|
|
|
void condenseSrcs(Instruction *, const int first, const int last);
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
void addHazard(Instruction *i, const ValueRef *src);
|
|
|
|
|
void textureMask(TexInstruction *);
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
// target specific functions, TODO: put in subclass or Target
|
|
|
|
|
void texConstraintNV50(TexInstruction *);
|
|
|
|
|
void texConstraintNVC0(TexInstruction *);
|
|
|
|
|
void texConstraintNVE0(TexInstruction *);
|
2014-05-09 15:56:05 +10:00
|
|
|
void texConstraintGM107(TexInstruction *);
|
2012-04-09 20:58:39 +02:00
|
|
|
|
2018-08-05 18:34:22 +02:00
|
|
|
bool isScalarTexGM107(TexInstruction *);
|
|
|
|
|
void handleScalarTexGM107(TexInstruction *);
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
std::list<Instruction *> constrList;
|
|
|
|
|
|
|
|
|
|
const Target *targ;
|
2011-09-14 16:18:23 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool buildLiveSets(BasicBlock *);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Program *prog;
|
|
|
|
|
Function *func;
|
|
|
|
|
|
|
|
|
|
// instructions in control flow / chronological order
|
|
|
|
|
ArrayList insns;
|
|
|
|
|
|
|
|
|
|
int sequence; // for manual passes through CFG
|
|
|
|
|
};
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
typedef std::pair<Value *, Value *> ValuePair;
|
|
|
|
|
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
class MergedDefs
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
std::list<ValueDef *>& entry(Value *val) {
|
|
|
|
|
auto it = defs.find(val);
|
|
|
|
|
|
|
|
|
|
if (it == defs.end()) {
|
|
|
|
|
std::list<ValueDef *> &res = defs[val];
|
|
|
|
|
res = val->defs;
|
|
|
|
|
return res;
|
|
|
|
|
} else {
|
|
|
|
|
return (*it).second;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_map<Value *, std::list<ValueDef *> > defs;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
std::list<ValueDef *>& operator()(Value *val) {
|
|
|
|
|
return entry(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void add(Value *val, const std::list<ValueDef *> &vals) {
|
|
|
|
|
assert(val);
|
|
|
|
|
std::list<ValueDef *> &valdefs = entry(val);
|
|
|
|
|
valdefs.insert(valdefs.end(), vals.begin(), vals.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void removeDefsOfInstruction(Instruction *insn) {
|
|
|
|
|
for (int d = 0; insn->defExists(d); ++d) {
|
|
|
|
|
ValueDef *def = &insn->def(d);
|
|
|
|
|
defs.erase(def->get());
|
|
|
|
|
for (auto &p : defs)
|
|
|
|
|
p.second.remove(def);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void merge() {
|
|
|
|
|
for (auto &p : defs)
|
|
|
|
|
p.first->defs = p.second;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
class SpillCodeInserter
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
public:
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
SpillCodeInserter(Function *fn, MergedDefs &mergedDefs) : func(fn), mergedDefs(mergedDefs), stackSize(0), stackBase(0) { }
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
bool run(const std::list<ValuePair>&);
|
|
|
|
|
|
2013-01-12 17:37:34 +01:00
|
|
|
Symbol *assignSlot(const Interval&, const unsigned int size);
|
2014-02-19 04:00:34 +01:00
|
|
|
Value *offsetSlot(Value *, const LValue *);
|
2012-04-09 20:58:39 +02:00
|
|
|
inline int32_t getStackSize() const { return stackSize; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Function *func;
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
MergedDefs &mergedDefs;
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
int32_t stackSize;
|
|
|
|
|
int32_t stackBase;
|
|
|
|
|
|
|
|
|
|
LValue *unspill(Instruction *usei, LValue *, Value *slot);
|
|
|
|
|
void spill(Instruction *defi, Value *slot, LValue *);
|
|
|
|
|
};
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::BuildIntervalsPass::addLiveRange(Value *val,
|
|
|
|
|
const BasicBlock *bb,
|
|
|
|
|
int end)
|
|
|
|
|
{
|
|
|
|
|
Instruction *insn = val->getUniqueInsn();
|
|
|
|
|
|
|
|
|
|
if (!insn)
|
2012-04-06 19:16:04 +02:00
|
|
|
insn = bb->getFirst();
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
assert(bb->getFirst()->serial <= bb->getExit()->serial);
|
|
|
|
|
assert(bb->getExit()->serial + 1 >= end);
|
|
|
|
|
|
|
|
|
|
int begin = insn->serial;
|
|
|
|
|
if (begin < bb->getEntry()->serial || begin > bb->getExit()->serial)
|
|
|
|
|
begin = bb->getEntry()->serial;
|
|
|
|
|
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "%%%i <- live range [%i(%i), %i)\n",
|
|
|
|
|
val->id, begin, insn->serial, end);
|
|
|
|
|
|
|
|
|
|
if (begin != end) // empty ranges are only added as hazards for fixed regs
|
|
|
|
|
val->livei.extend(begin, end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::PhiMovesPass::needNewElseBlock(BasicBlock *b, BasicBlock *p)
|
|
|
|
|
{
|
|
|
|
|
if (b->cfg.incidentCount() <= 1)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
int n = 0;
|
|
|
|
|
for (Graph::EdgeIterator ei = p->cfg.outgoing(); !ei.end(); ei.next())
|
|
|
|
|
if (ei.getType() == Graph::Edge::TREE ||
|
|
|
|
|
ei.getType() == Graph::Edge::FORWARD)
|
|
|
|
|
++n;
|
|
|
|
|
return (n == 2);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-10 01:54:30 -04:00
|
|
|
struct PhiMapHash {
|
|
|
|
|
size_t operator()(const std::pair<Instruction *, BasicBlock *>& val) const {
|
2022-06-18 16:45:53 -04:00
|
|
|
return std::hash<Instruction*>()(val.first) * 31 +
|
|
|
|
|
std::hash<BasicBlock*>()(val.second);
|
2015-09-10 01:54:30 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-06-18 16:45:53 -04:00
|
|
|
typedef std::unordered_map<
|
2015-09-10 01:54:30 -04:00
|
|
|
std::pair<Instruction *, BasicBlock *>, Value *, PhiMapHash> PhiMap;
|
|
|
|
|
|
|
|
|
|
// Critical edges need to be split up so that work can be inserted along
|
|
|
|
|
// specific edge transitions. Unfortunately manipulating incident edges into a
|
|
|
|
|
// BB invalidates all the PHI nodes since their sources are implicitly ordered
|
|
|
|
|
// by incident edge order.
|
2011-09-14 16:18:23 +02:00
|
|
|
//
|
2015-09-10 01:54:30 -04:00
|
|
|
// TODO: Make it so that that is not the case, and PHI nodes store pointers to
|
|
|
|
|
// the original BBs.
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::PhiMovesPass::splitEdges(BasicBlock *bb)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
|
|
|
|
BasicBlock *pb, *pn;
|
2015-09-10 01:54:30 -04:00
|
|
|
Instruction *phi;
|
|
|
|
|
Graph::EdgeIterator ei;
|
2012-04-09 20:58:39 +02:00
|
|
|
std::stack<BasicBlock *> stack;
|
2015-09-10 01:54:30 -04:00
|
|
|
int j = 0;
|
2012-04-09 20:58:39 +02:00
|
|
|
|
2015-09-10 01:54:30 -04:00
|
|
|
for (ei = bb->cfg.incident(); !ei.end(); ei.next()) {
|
2012-04-09 20:58:39 +02:00
|
|
|
pb = BasicBlock::get(ei.getNode());
|
2011-09-14 16:18:23 +02:00
|
|
|
assert(pb);
|
2012-04-09 20:58:39 +02:00
|
|
|
if (needNewElseBlock(bb, pb))
|
|
|
|
|
stack.push(pb);
|
|
|
|
|
}
|
2015-09-10 01:54:30 -04:00
|
|
|
|
|
|
|
|
// No critical edges were found, no need to perform any work.
|
|
|
|
|
if (stack.empty())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// We're about to, potentially, reorder the inbound edges. This means that
|
|
|
|
|
// we need to hold on to the (phi, bb) -> src mapping, and fix up the phi
|
|
|
|
|
// nodes after the graph has been modified.
|
|
|
|
|
PhiMap phis;
|
|
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
|
for (ei = bb->cfg.incident(); !ei.end(); ei.next(), j++) {
|
|
|
|
|
pb = BasicBlock::get(ei.getNode());
|
|
|
|
|
for (phi = bb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next)
|
|
|
|
|
phis.insert(std::make_pair(std::make_pair(phi, pb), phi->getSrc(j)));
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
while (!stack.empty()) {
|
|
|
|
|
pb = stack.top();
|
|
|
|
|
pn = new BasicBlock(func);
|
|
|
|
|
stack.pop();
|
|
|
|
|
|
|
|
|
|
pb->cfg.detach(&bb->cfg);
|
|
|
|
|
pb->cfg.attach(&pn->cfg, Graph::Edge::TREE);
|
|
|
|
|
pn->cfg.attach(&bb->cfg, Graph::Edge::FORWARD);
|
|
|
|
|
|
|
|
|
|
assert(pb->getExit()->op != OP_CALL);
|
|
|
|
|
if (pb->getExit()->asFlow()->target.bb == bb)
|
|
|
|
|
pb->getExit()->asFlow()->target.bb = pn;
|
2015-09-10 01:54:30 -04:00
|
|
|
|
|
|
|
|
for (phi = bb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) {
|
|
|
|
|
PhiMap::iterator it = phis.find(std::make_pair(phi, pb));
|
|
|
|
|
assert(it != phis.end());
|
|
|
|
|
phis.insert(std::make_pair(std::make_pair(phi, pn), it->second));
|
|
|
|
|
phis.erase(it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now go through and fix up all of the phi node sources.
|
|
|
|
|
j = 0;
|
|
|
|
|
for (ei = bb->cfg.incident(); !ei.end(); ei.next(), j++) {
|
|
|
|
|
pb = BasicBlock::get(ei.getNode());
|
|
|
|
|
for (phi = bb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) {
|
|
|
|
|
PhiMap::const_iterator it = phis.find(std::make_pair(phi, pb));
|
|
|
|
|
assert(it != phis.end());
|
|
|
|
|
|
|
|
|
|
phi->setSrc(j, it->second);
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
2015-09-10 01:54:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For each operand of each PHI in b, generate a new value by inserting a MOV
|
|
|
|
|
// at the end of the block it is coming from and replace the operand with its
|
|
|
|
|
// result. This eliminates liveness conflicts and enables us to let values be
|
|
|
|
|
// copied to the right register if such a conflict exists nonetheless.
|
|
|
|
|
//
|
|
|
|
|
// These MOVs are also crucial in making sure the live intervals of phi srces
|
|
|
|
|
// are extended until the end of the loop, since they are not included in the
|
|
|
|
|
// live-in sets.
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::PhiMovesPass::visit(BasicBlock *bb)
|
|
|
|
|
{
|
|
|
|
|
Instruction *phi, *mov;
|
|
|
|
|
|
|
|
|
|
splitEdges(bb);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:40:35 +02:00
|
|
|
// insert MOVs (phi->src(j) should stem from j-th in-BB)
|
2011-09-14 16:18:23 +02:00
|
|
|
int j = 0;
|
|
|
|
|
for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) {
|
2015-09-10 01:54:30 -04:00
|
|
|
BasicBlock *pb = BasicBlock::get(ei.getNode());
|
2011-09-14 16:18:23 +02:00
|
|
|
if (!pb->isTerminated())
|
|
|
|
|
pb->insertTail(new_FlowInstruction(func, OP_BRA, bb));
|
|
|
|
|
|
|
|
|
|
for (phi = bb->getPhi(); phi && phi->op == OP_PHI; phi = phi->next) {
|
2014-07-16 23:20:57 -04:00
|
|
|
LValue *tmp = new_LValue(func, phi->getDef(0)->asLValue());
|
|
|
|
|
mov = new_Instruction(func, OP_MOV, typeOfSize(tmp->reg.size));
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
mov->setSrc(0, phi->getSrc(j));
|
2014-07-16 23:20:57 -04:00
|
|
|
mov->setDef(0, tmp);
|
|
|
|
|
phi->setSrc(j, tmp);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
pb->insertBefore(pb->getExit(), mov);
|
|
|
|
|
}
|
|
|
|
|
++j;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build the set of live-in variables of bb.
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::buildLiveSets(BasicBlock *bb)
|
|
|
|
|
{
|
2012-04-06 19:16:04 +02:00
|
|
|
Function *f = bb->getFunction();
|
2011-09-14 16:18:23 +02:00
|
|
|
BasicBlock *bn;
|
|
|
|
|
Instruction *i;
|
|
|
|
|
unsigned int s, d;
|
|
|
|
|
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "buildLiveSets(BB:%i)\n", bb->getId());
|
|
|
|
|
|
|
|
|
|
bb->liveSet.allocate(func->allLValues.getSize(), false);
|
|
|
|
|
|
|
|
|
|
int n = 0;
|
|
|
|
|
for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
|
|
|
|
|
bn = BasicBlock::get(ei.getNode());
|
|
|
|
|
if (bn == bb)
|
|
|
|
|
continue;
|
|
|
|
|
if (bn->cfg.visit(sequence))
|
|
|
|
|
if (!buildLiveSets(bn))
|
|
|
|
|
return false;
|
2011-12-27 12:43:27 +01:00
|
|
|
if (n++ || bb->liveSet.marker)
|
2011-09-14 16:18:23 +02:00
|
|
|
bb->liveSet |= bn->liveSet;
|
2011-12-27 12:43:27 +01:00
|
|
|
else
|
|
|
|
|
bb->liveSet = bn->liveSet;
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
if (!n && !bb->liveSet.marker)
|
|
|
|
|
bb->liveSet.fill(0);
|
|
|
|
|
bb->liveSet.marker = true;
|
|
|
|
|
|
|
|
|
|
if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC) {
|
|
|
|
|
INFO("BB:%i live set of out blocks:\n", bb->getId());
|
|
|
|
|
bb->liveSet.print();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if (!bb->getEntry())
|
|
|
|
|
// return true;
|
|
|
|
|
|
2012-04-06 19:16:04 +02:00
|
|
|
if (bb == BasicBlock::get(f->cfgExit)) {
|
|
|
|
|
for (std::deque<ValueRef>::iterator it = f->outs.begin();
|
|
|
|
|
it != f->outs.end(); ++it) {
|
|
|
|
|
assert(it->get()->asLValue());
|
|
|
|
|
bb->liveSet.set(it->get()->id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
for (i = bb->getExit(); i && i != bb->getEntry()->prev; i = i->prev) {
|
|
|
|
|
for (d = 0; i->defExists(d); ++d)
|
|
|
|
|
bb->liveSet.clr(i->getDef(d)->id);
|
|
|
|
|
for (s = 0; i->srcExists(s); ++s)
|
|
|
|
|
if (i->getSrc(s)->asLValue())
|
|
|
|
|
bb->liveSet.set(i->getSrc(s)->id);
|
|
|
|
|
}
|
|
|
|
|
for (i = bb->getPhi(); i && i->op == OP_PHI; i = i->next)
|
|
|
|
|
bb->liveSet.clr(i->getDef(0)->id);
|
|
|
|
|
|
|
|
|
|
if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC) {
|
|
|
|
|
INFO("BB:%i live set after propagation:\n", bb->getId());
|
|
|
|
|
bb->liveSet.print();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::BuildIntervalsPass::collectLiveValues(BasicBlock *bb)
|
|
|
|
|
{
|
|
|
|
|
BasicBlock *bbA = NULL, *bbB = NULL;
|
|
|
|
|
|
|
|
|
|
if (bb->cfg.outgoingCount()) {
|
|
|
|
|
// trickery to save a loop of OR'ing liveSets
|
|
|
|
|
// aliasing works fine with BitSet::setOr
|
|
|
|
|
for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
|
|
|
|
|
if (bbA) {
|
|
|
|
|
bb->liveSet.setOr(&bbA->liveSet, &bbB->liveSet);
|
|
|
|
|
bbA = bb;
|
|
|
|
|
} else {
|
|
|
|
|
bbA = bbB;
|
|
|
|
|
}
|
|
|
|
|
bbB = BasicBlock::get(ei.getNode());
|
|
|
|
|
}
|
|
|
|
|
bb->liveSet.setOr(&bbB->liveSet, bbA ? &bbA->liveSet : NULL);
|
|
|
|
|
} else
|
|
|
|
|
if (bb->cfg.incidentCount()) {
|
|
|
|
|
bb->liveSet.fill(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::BuildIntervalsPass::visit(BasicBlock *bb)
|
|
|
|
|
{
|
|
|
|
|
collectLiveValues(bb);
|
|
|
|
|
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "BuildIntervals(BB:%i)\n", bb->getId());
|
|
|
|
|
|
|
|
|
|
// go through out blocks and delete phi sources that do not originate from
|
|
|
|
|
// the current block from the live set
|
|
|
|
|
for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
|
|
|
|
|
BasicBlock *out = BasicBlock::get(ei.getNode());
|
|
|
|
|
|
|
|
|
|
for (Instruction *i = out->getPhi(); i && i->op == OP_PHI; i = i->next) {
|
|
|
|
|
bb->liveSet.clr(i->getDef(0)->id);
|
|
|
|
|
|
2012-03-29 21:18:24 +02:00
|
|
|
for (int s = 0; i->srcExists(s); ++s) {
|
2012-04-09 20:40:35 +02:00
|
|
|
assert(i->src(s).getInsn());
|
2011-09-14 16:18:23 +02:00
|
|
|
if (i->getSrc(s)->getUniqueInsn()->bb == bb) // XXX: reachableBy ?
|
|
|
|
|
bb->liveSet.set(i->getSrc(s)->id);
|
|
|
|
|
else
|
|
|
|
|
bb->liveSet.clr(i->getSrc(s)->id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remaining live-outs are live until end
|
|
|
|
|
if (bb->getExit()) {
|
|
|
|
|
for (unsigned int j = 0; j < bb->liveSet.getSize(); ++j)
|
|
|
|
|
if (bb->liveSet.test(j))
|
|
|
|
|
addLiveRange(func->getLValue(j), bb, bb->getExit()->serial + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (Instruction *i = bb->getExit(); i && i->op != OP_PHI; i = i->prev) {
|
|
|
|
|
for (int d = 0; i->defExists(d); ++d) {
|
|
|
|
|
bb->liveSet.clr(i->getDef(d)->id);
|
|
|
|
|
if (i->getDef(d)->reg.data.id >= 0) // add hazard for fixed regs
|
|
|
|
|
i->getDef(d)->livei.extend(i->serial, i->serial);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int s = 0; i->srcExists(s); ++s) {
|
|
|
|
|
if (!i->getSrc(s)->asLValue())
|
|
|
|
|
continue;
|
|
|
|
|
if (!bb->liveSet.test(i->getSrc(s)->id)) {
|
|
|
|
|
bb->liveSet.set(i->getSrc(s)->id);
|
|
|
|
|
addLiveRange(i->getSrc(s), bb, i->serial);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-06 19:16:04 +02:00
|
|
|
if (bb == BasicBlock::get(func->cfg.getRoot())) {
|
|
|
|
|
for (std::deque<ValueDef>::iterator it = func->ins.begin();
|
|
|
|
|
it != func->ins.end(); ++it) {
|
|
|
|
|
if (it->get()->reg.data.id >= 0) // add hazard for fixed regs
|
|
|
|
|
it->get()->livei.extend(0, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
#define JOIN_MASK_PHI (1 << 0)
|
|
|
|
|
#define JOIN_MASK_UNION (1 << 1)
|
|
|
|
|
#define JOIN_MASK_MOV (1 << 2)
|
|
|
|
|
#define JOIN_MASK_TEX (1 << 3)
|
|
|
|
|
|
|
|
|
|
class GCRA
|
|
|
|
|
{
|
|
|
|
|
public:
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
GCRA(Function *, SpillCodeInserter&, MergedDefs&);
|
2012-04-09 20:58:39 +02:00
|
|
|
~GCRA();
|
|
|
|
|
|
|
|
|
|
bool allocateRegisters(ArrayList& insns);
|
|
|
|
|
|
|
|
|
|
void printNodeInfo() const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
class RIG_Node : public Graph::Node
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
RIG_Node();
|
|
|
|
|
|
|
|
|
|
void init(const RegisterSet&, LValue *);
|
|
|
|
|
|
|
|
|
|
void addInterference(RIG_Node *);
|
|
|
|
|
void addRegPreference(RIG_Node *);
|
|
|
|
|
|
|
|
|
|
inline LValue *getValue() const
|
|
|
|
|
{
|
|
|
|
|
return reinterpret_cast<LValue *>(data);
|
|
|
|
|
}
|
|
|
|
|
inline void setValue(LValue *lval) { data = lval; }
|
|
|
|
|
|
|
|
|
|
inline uint8_t getCompMask() const
|
|
|
|
|
{
|
|
|
|
|
return ((1 << colors) - 1) << (reg & 7);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline RIG_Node *get(const Graph::EdgeIterator& ei)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<RIG_Node *>(ei.getNode());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
uint32_t degree;
|
|
|
|
|
uint16_t degreeLimit; // if deg < degLimit, node is trivially colourable
|
2018-11-11 15:52:33 -05:00
|
|
|
uint16_t maxReg;
|
2012-04-09 20:58:39 +02:00
|
|
|
uint16_t colors;
|
|
|
|
|
|
|
|
|
|
DataFile f;
|
|
|
|
|
int32_t reg;
|
|
|
|
|
|
|
|
|
|
float weight;
|
|
|
|
|
|
|
|
|
|
// list pointers for simplify() phase
|
|
|
|
|
RIG_Node *next;
|
|
|
|
|
RIG_Node *prev;
|
|
|
|
|
|
|
|
|
|
// union of the live intervals of all coalesced values (we want to retain
|
|
|
|
|
// the separate intervals for testing interference of compound values)
|
|
|
|
|
Interval livei;
|
|
|
|
|
|
|
|
|
|
std::list<RIG_Node *> prefRegs;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
inline RIG_Node *getNode(const LValue *v) const { return &nodes[v->id]; }
|
|
|
|
|
|
|
|
|
|
void buildRIG(ArrayList&);
|
|
|
|
|
bool coalesce(ArrayList&);
|
|
|
|
|
bool doCoalesce(ArrayList&, unsigned int mask);
|
|
|
|
|
void calculateSpillWeights();
|
2016-10-03 18:55:09 +02:00
|
|
|
bool simplify();
|
2012-04-09 20:58:39 +02:00
|
|
|
bool selectRegisters();
|
|
|
|
|
void cleanup(const bool success);
|
|
|
|
|
|
|
|
|
|
void simplifyEdge(RIG_Node *, RIG_Node *);
|
|
|
|
|
void simplifyNode(RIG_Node *);
|
|
|
|
|
|
nv50/ir/ra: Fix copying compound for moves
In order to reduce moves when coalescing multiple registers into a
larger register, RA will try to coalesce MERGE instructions with their
definitions. For example, for something like this in GLSL:
uint a = ...;
uint b = ...;
uint64 x = packUint2x32(a, b);
The compiler will try to coalesce x with a and b, in the same way as
something like:
uint a = ...;
uint b = ...;
...
uint x = phi(a, b);
with the crucial difference that the definitions of a and b only clobber
part of the register, instead of the whole thing. This information is
carried through the compound flag and compMask bitmask. If compound is
set, then the value has been coalesced in such a way that not all the
defs clobber the entire register. The compMask bitmask describes which
subregister each def clobbers, although it does it in a slightly
convoluted way. It's an invariant that once compound is set on one def,
it must be set for all the defs in a given coalesced value.
In more detail, the constraints pass will first create extra moves:
uint a = ...;
uint b = ...;
uint a' = a;
uint b' = b;
uint64 x = packUint2x32(a', b');
and then RA will merge values involved in MERGE/SPLIT instructions,
merging x with a' and b' and making the combined value compound -- this
is relatively simple, and will always succeed since we just created a'
and b', so they never interfere with x, and x has no other definitions,
since we haven't started coalescing moves yet. Basically, we just replaced
the MERGE instruction with an equivalent sequence of partial writes to the
destination. The tricky part comes when we try to merge a' with a
and b' with b. We need to transfer the compound information from a' to a
and b' to b, which copyCompound() does, but we also need to transfer it
to any defs coalesced with a and b, which the code failed to do. Similarly,
if x is the argument to a phi instruction, then when we try to merge it
with other arguments to the same phi by coalescing moves, we'd have
problems guaranteeing that all the other merged defs stay up-to-date.
One tricky part of fixing this is that in order to properly propagate
the information from a' to a, we need to do it before the defs for a and
a' are merged in coalesceValues(), since we need to know which defs are
merged with a but not a' -- after coalesceValues() returns, all the defs
have been combined, so we don't know which is which. I took the approach
of calling copyCompound() inside coalesceValues(), instead of
afterwards.
v2: (mhenning) This now loops over mergedDefs in copyCompound, to update
it for changes made in bcf6a9ec
Cc: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: Karol Herbst <kherbst@redhat.com>
Tested-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17115>
2018-01-08 19:25:01 -05:00
|
|
|
void copyCompound(Value *dst, Value *src);
|
2012-04-09 20:58:39 +02:00
|
|
|
bool coalesceValues(Value *, Value *, bool force);
|
|
|
|
|
void resolveSplitsAndMerges();
|
|
|
|
|
void makeCompound(Instruction *, bool isSplit);
|
|
|
|
|
|
|
|
|
|
inline void checkInterference(const RIG_Node *, Graph::EdgeIterator&);
|
|
|
|
|
|
|
|
|
|
inline void insertOrderedTail(std::list<RIG_Node *>&, RIG_Node *);
|
|
|
|
|
void checkList(std::list<RIG_Node *>&);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::stack<uint32_t> stack;
|
|
|
|
|
|
|
|
|
|
// list headers for simplify() phase
|
|
|
|
|
RIG_Node lo[2];
|
|
|
|
|
RIG_Node hi;
|
|
|
|
|
|
|
|
|
|
Graph RIG;
|
|
|
|
|
RIG_Node *nodes;
|
|
|
|
|
unsigned int nodeCount;
|
|
|
|
|
|
|
|
|
|
Function *func;
|
|
|
|
|
Program *prog;
|
|
|
|
|
|
2018-12-07 09:47:05 +01:00
|
|
|
struct RelDegree {
|
|
|
|
|
uint8_t data[17][17];
|
|
|
|
|
|
|
|
|
|
RelDegree() {
|
|
|
|
|
for (int i = 1; i <= 16; ++i)
|
|
|
|
|
for (int j = 1; j <= 16; ++j)
|
|
|
|
|
data[i][j] = j * ((i + j - 1) / j);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const uint8_t* operator[](std::size_t i) const {
|
|
|
|
|
return data[i];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const RelDegree relDegree;
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
RegisterSet regs;
|
|
|
|
|
|
|
|
|
|
// need to fixup register id for participants of OP_MERGE/SPLIT
|
|
|
|
|
std::list<Instruction *> merges;
|
|
|
|
|
std::list<Instruction *> splits;
|
|
|
|
|
|
|
|
|
|
SpillCodeInserter& spill;
|
|
|
|
|
std::list<ValuePair> mustSpill;
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
|
|
|
|
|
MergedDefs &mergedDefs;
|
2012-04-09 20:58:39 +02:00
|
|
|
};
|
|
|
|
|
|
2018-12-07 09:47:05 +01:00
|
|
|
const GCRA::RelDegree GCRA::relDegree;
|
2012-04-09 20:58:39 +02:00
|
|
|
|
2021-05-08 16:59:15 -07:00
|
|
|
GCRA::RIG_Node::RIG_Node() : Node(NULL), degree(0), degreeLimit(0), maxReg(0),
|
|
|
|
|
colors(0), f(FILE_NULL), reg(0), weight(0), next(this), prev(this)
|
2012-04-09 20:58:39 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GCRA::printNodeInfo() const
|
|
|
|
|
{
|
|
|
|
|
for (unsigned int i = 0; i < nodeCount; ++i) {
|
|
|
|
|
if (!nodes[i].colors)
|
|
|
|
|
continue;
|
|
|
|
|
INFO("RIG_Node[%%%i]($[%u]%i): %u colors, weight %f, deg %u/%u\n X",
|
|
|
|
|
i,
|
|
|
|
|
nodes[i].f,nodes[i].reg,nodes[i].colors,
|
|
|
|
|
nodes[i].weight,
|
|
|
|
|
nodes[i].degree, nodes[i].degreeLimit);
|
|
|
|
|
|
|
|
|
|
for (Graph::EdgeIterator ei = nodes[i].outgoing(); !ei.end(); ei.next())
|
|
|
|
|
INFO(" %%%i", RIG_Node::get(ei)->getValue()->id);
|
|
|
|
|
for (Graph::EdgeIterator ei = nodes[i].incident(); !ei.end(); ei.next())
|
|
|
|
|
INFO(" %%%i", RIG_Node::get(ei)->getValue()->id);
|
|
|
|
|
INFO("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-08 18:21:26 -05:00
|
|
|
static bool
|
|
|
|
|
isShortRegOp(Instruction *insn)
|
|
|
|
|
{
|
2018-11-11 10:55:55 -05:00
|
|
|
// Immediates are always in src1 (except zeroes, which end up getting
|
|
|
|
|
// replaced with a zero reg). Every other situation can be resolved by
|
2015-12-08 18:21:26 -05:00
|
|
|
// using a long encoding.
|
2018-11-11 10:55:55 -05:00
|
|
|
return insn->srcExists(1) && insn->src(1).getFile() == FILE_IMMEDIATE &&
|
|
|
|
|
insn->getSrc(1)->reg.data.u64;
|
2015-12-08 18:21:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if this LValue is ever used in an instruction that can't be encoded
|
|
|
|
|
// with long registers (i.e. > r63)
|
|
|
|
|
static bool
|
|
|
|
|
isShortRegVal(LValue *lval)
|
|
|
|
|
{
|
2016-03-19 14:04:54 +01:00
|
|
|
if (lval->getInsn() == NULL)
|
2015-12-08 18:21:26 -05:00
|
|
|
return false;
|
|
|
|
|
for (Value::DefCIterator def = lval->defs.begin();
|
|
|
|
|
def != lval->defs.end(); ++def)
|
|
|
|
|
if (isShortRegOp((*def)->getInsn()))
|
|
|
|
|
return true;
|
|
|
|
|
for (Value::UseCIterator use = lval->uses.begin();
|
|
|
|
|
use != lval->uses.end(); ++use)
|
|
|
|
|
if (isShortRegOp((*use)->getInsn()))
|
|
|
|
|
return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
GCRA::RIG_Node::init(const RegisterSet& regs, LValue *lval)
|
|
|
|
|
{
|
|
|
|
|
setValue(lval);
|
|
|
|
|
if (lval->reg.data.id >= 0)
|
|
|
|
|
lval->noSpill = lval->fixedReg = 1;
|
|
|
|
|
|
|
|
|
|
colors = regs.units(lval->reg.file, lval->reg.size);
|
|
|
|
|
f = lval->reg.file;
|
|
|
|
|
reg = -1;
|
|
|
|
|
if (lval->reg.data.id >= 0)
|
|
|
|
|
reg = regs.idToUnits(lval);
|
|
|
|
|
|
|
|
|
|
weight = std::numeric_limits<float>::infinity();
|
|
|
|
|
degree = 0;
|
2018-11-11 15:52:33 -05:00
|
|
|
maxReg = regs.getFileSize(f);
|
2015-12-08 18:21:26 -05:00
|
|
|
// On nv50, we lose a bit of gpr encoding when there's an embedded
|
|
|
|
|
// immediate.
|
2018-11-11 10:55:55 -05:00
|
|
|
if (regs.restrictedGPR16Range && f == FILE_GPR && (lval->reg.size == 2 || isShortRegVal(lval)))
|
2018-11-11 15:52:33 -05:00
|
|
|
maxReg /= 2;
|
|
|
|
|
degreeLimit = maxReg;
|
2014-02-08 19:32:54 +01:00
|
|
|
degreeLimit -= relDegree[1][colors] - 1;
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
livei.insert(lval->livei);
|
|
|
|
|
}
|
|
|
|
|
|
nv50/ir/ra: Fix copying compound for moves
In order to reduce moves when coalescing multiple registers into a
larger register, RA will try to coalesce MERGE instructions with their
definitions. For example, for something like this in GLSL:
uint a = ...;
uint b = ...;
uint64 x = packUint2x32(a, b);
The compiler will try to coalesce x with a and b, in the same way as
something like:
uint a = ...;
uint b = ...;
...
uint x = phi(a, b);
with the crucial difference that the definitions of a and b only clobber
part of the register, instead of the whole thing. This information is
carried through the compound flag and compMask bitmask. If compound is
set, then the value has been coalesced in such a way that not all the
defs clobber the entire register. The compMask bitmask describes which
subregister each def clobbers, although it does it in a slightly
convoluted way. It's an invariant that once compound is set on one def,
it must be set for all the defs in a given coalesced value.
In more detail, the constraints pass will first create extra moves:
uint a = ...;
uint b = ...;
uint a' = a;
uint b' = b;
uint64 x = packUint2x32(a', b');
and then RA will merge values involved in MERGE/SPLIT instructions,
merging x with a' and b' and making the combined value compound -- this
is relatively simple, and will always succeed since we just created a'
and b', so they never interfere with x, and x has no other definitions,
since we haven't started coalescing moves yet. Basically, we just replaced
the MERGE instruction with an equivalent sequence of partial writes to the
destination. The tricky part comes when we try to merge a' with a
and b' with b. We need to transfer the compound information from a' to a
and b' to b, which copyCompound() does, but we also need to transfer it
to any defs coalesced with a and b, which the code failed to do. Similarly,
if x is the argument to a phi instruction, then when we try to merge it
with other arguments to the same phi by coalescing moves, we'd have
problems guaranteeing that all the other merged defs stay up-to-date.
One tricky part of fixing this is that in order to properly propagate
the information from a' to a, we need to do it before the defs for a and
a' are merged in coalesceValues(), since we need to know which defs are
merged with a but not a' -- after coalesceValues() returns, all the defs
have been combined, so we don't know which is which. I took the approach
of calling copyCompound() inside coalesceValues(), instead of
afterwards.
v2: (mhenning) This now loops over mergedDefs in copyCompound, to update
it for changes made in bcf6a9ec
Cc: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: Karol Herbst <kherbst@redhat.com>
Tested-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17115>
2018-01-08 19:25:01 -05:00
|
|
|
// Used when coalescing moves. The non-compound value will become one, e.g.:
|
|
|
|
|
// mov b32 $r0 $r2 / merge b64 $r0d { $r0 $r1 }
|
|
|
|
|
// split b64 { $r0 $r1 } $r0d / mov b64 $r0d f64 $r2d
|
|
|
|
|
void
|
|
|
|
|
GCRA::copyCompound(Value *dst, Value *src)
|
|
|
|
|
{
|
|
|
|
|
LValue *ldst = dst->asLValue();
|
|
|
|
|
LValue *lsrc = src->asLValue();
|
|
|
|
|
|
|
|
|
|
if (ldst->compound && !lsrc->compound) {
|
|
|
|
|
LValue *swap = lsrc;
|
|
|
|
|
lsrc = ldst;
|
|
|
|
|
ldst = swap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(!ldst->compound);
|
|
|
|
|
|
|
|
|
|
if (lsrc->compound) {
|
|
|
|
|
for (ValueDef *d : mergedDefs(ldst->join)) {
|
|
|
|
|
LValue *ldst = d->get()->asLValue();
|
|
|
|
|
if (!ldst->compound)
|
|
|
|
|
ldst->compMask = 0xff;
|
|
|
|
|
ldst->compound = 1;
|
|
|
|
|
ldst->compMask &= lsrc->compMask;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
bool
|
|
|
|
|
GCRA::coalesceValues(Value *dst, Value *src, bool force)
|
|
|
|
|
{
|
|
|
|
|
LValue *rep = dst->join->asLValue();
|
|
|
|
|
LValue *val = src->join->asLValue();
|
|
|
|
|
|
|
|
|
|
if (!force && val->reg.data.id >= 0) {
|
|
|
|
|
rep = src->join->asLValue();
|
|
|
|
|
val = dst->join->asLValue();
|
|
|
|
|
}
|
|
|
|
|
RIG_Node *nRep = &nodes[rep->id];
|
|
|
|
|
RIG_Node *nVal = &nodes[val->id];
|
|
|
|
|
|
|
|
|
|
if (src->reg.file != dst->reg.file) {
|
|
|
|
|
if (!force)
|
|
|
|
|
return false;
|
|
|
|
|
WARN("forced coalescing of values in different files !\n");
|
|
|
|
|
}
|
|
|
|
|
if (!force && dst->reg.size != src->reg.size)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if ((rep->reg.data.id >= 0) && (rep->reg.data.id != val->reg.data.id)) {
|
|
|
|
|
if (force) {
|
|
|
|
|
if (val->reg.data.id >= 0)
|
|
|
|
|
WARN("forced coalescing of values in different fixed regs !\n");
|
|
|
|
|
} else {
|
|
|
|
|
if (val->reg.data.id >= 0)
|
|
|
|
|
return false;
|
|
|
|
|
// make sure that there is no overlap with the fixed register of rep
|
|
|
|
|
for (ArrayList::Iterator it = func->allLValues.iterator();
|
|
|
|
|
!it.end(); it.next()) {
|
|
|
|
|
Value *reg = reinterpret_cast<Value *>(it.get())->asLValue();
|
|
|
|
|
assert(reg);
|
|
|
|
|
if (reg->interfers(rep) && reg->livei.overlaps(nVal->livei))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!force && nRep->livei.overlaps(nVal->livei))
|
|
|
|
|
return false;
|
|
|
|
|
|
nv50/ir/ra: Fix copying compound for moves
In order to reduce moves when coalescing multiple registers into a
larger register, RA will try to coalesce MERGE instructions with their
definitions. For example, for something like this in GLSL:
uint a = ...;
uint b = ...;
uint64 x = packUint2x32(a, b);
The compiler will try to coalesce x with a and b, in the same way as
something like:
uint a = ...;
uint b = ...;
...
uint x = phi(a, b);
with the crucial difference that the definitions of a and b only clobber
part of the register, instead of the whole thing. This information is
carried through the compound flag and compMask bitmask. If compound is
set, then the value has been coalesced in such a way that not all the
defs clobber the entire register. The compMask bitmask describes which
subregister each def clobbers, although it does it in a slightly
convoluted way. It's an invariant that once compound is set on one def,
it must be set for all the defs in a given coalesced value.
In more detail, the constraints pass will first create extra moves:
uint a = ...;
uint b = ...;
uint a' = a;
uint b' = b;
uint64 x = packUint2x32(a', b');
and then RA will merge values involved in MERGE/SPLIT instructions,
merging x with a' and b' and making the combined value compound -- this
is relatively simple, and will always succeed since we just created a'
and b', so they never interfere with x, and x has no other definitions,
since we haven't started coalescing moves yet. Basically, we just replaced
the MERGE instruction with an equivalent sequence of partial writes to the
destination. The tricky part comes when we try to merge a' with a
and b' with b. We need to transfer the compound information from a' to a
and b' to b, which copyCompound() does, but we also need to transfer it
to any defs coalesced with a and b, which the code failed to do. Similarly,
if x is the argument to a phi instruction, then when we try to merge it
with other arguments to the same phi by coalescing moves, we'd have
problems guaranteeing that all the other merged defs stay up-to-date.
One tricky part of fixing this is that in order to properly propagate
the information from a' to a, we need to do it before the defs for a and
a' are merged in coalesceValues(), since we need to know which defs are
merged with a but not a' -- after coalesceValues() returns, all the defs
have been combined, so we don't know which is which. I took the approach
of calling copyCompound() inside coalesceValues(), instead of
afterwards.
v2: (mhenning) This now loops over mergedDefs in copyCompound, to update
it for changes made in bcf6a9ec
Cc: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: Karol Herbst <kherbst@redhat.com>
Tested-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17115>
2018-01-08 19:25:01 -05:00
|
|
|
// TODO: Handle this case properly.
|
|
|
|
|
if (!force && rep->compound && val->compound)
|
|
|
|
|
return false;
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "joining %%%i($%i) <- %%%i\n",
|
|
|
|
|
rep->id, rep->reg.data.id, val->id);
|
|
|
|
|
|
nv50/ir/ra: Fix copying compound for moves
In order to reduce moves when coalescing multiple registers into a
larger register, RA will try to coalesce MERGE instructions with their
definitions. For example, for something like this in GLSL:
uint a = ...;
uint b = ...;
uint64 x = packUint2x32(a, b);
The compiler will try to coalesce x with a and b, in the same way as
something like:
uint a = ...;
uint b = ...;
...
uint x = phi(a, b);
with the crucial difference that the definitions of a and b only clobber
part of the register, instead of the whole thing. This information is
carried through the compound flag and compMask bitmask. If compound is
set, then the value has been coalesced in such a way that not all the
defs clobber the entire register. The compMask bitmask describes which
subregister each def clobbers, although it does it in a slightly
convoluted way. It's an invariant that once compound is set on one def,
it must be set for all the defs in a given coalesced value.
In more detail, the constraints pass will first create extra moves:
uint a = ...;
uint b = ...;
uint a' = a;
uint b' = b;
uint64 x = packUint2x32(a', b');
and then RA will merge values involved in MERGE/SPLIT instructions,
merging x with a' and b' and making the combined value compound -- this
is relatively simple, and will always succeed since we just created a'
and b', so they never interfere with x, and x has no other definitions,
since we haven't started coalescing moves yet. Basically, we just replaced
the MERGE instruction with an equivalent sequence of partial writes to the
destination. The tricky part comes when we try to merge a' with a
and b' with b. We need to transfer the compound information from a' to a
and b' to b, which copyCompound() does, but we also need to transfer it
to any defs coalesced with a and b, which the code failed to do. Similarly,
if x is the argument to a phi instruction, then when we try to merge it
with other arguments to the same phi by coalescing moves, we'd have
problems guaranteeing that all the other merged defs stay up-to-date.
One tricky part of fixing this is that in order to properly propagate
the information from a' to a, we need to do it before the defs for a and
a' are merged in coalesceValues(), since we need to know which defs are
merged with a but not a' -- after coalesceValues() returns, all the defs
have been combined, so we don't know which is which. I took the approach
of calling copyCompound() inside coalesceValues(), instead of
afterwards.
v2: (mhenning) This now loops over mergedDefs in copyCompound, to update
it for changes made in bcf6a9ec
Cc: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: Karol Herbst <kherbst@redhat.com>
Tested-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17115>
2018-01-08 19:25:01 -05:00
|
|
|
if (!force)
|
|
|
|
|
copyCompound(dst, src);
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
// set join pointer of all values joined with val
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
const std::list<ValueDef *> &defs = mergedDefs(val);
|
|
|
|
|
for (ValueDef *def : defs)
|
2020-01-15 20:37:27 +01:00
|
|
|
def->get()->join = rep;
|
2012-04-09 20:58:39 +02:00
|
|
|
assert(rep->join == rep && val->join == rep);
|
|
|
|
|
|
|
|
|
|
// add val's definitions to rep and extend the live interval of its RIG node
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
mergedDefs.add(rep, defs);
|
2012-04-09 20:58:39 +02:00
|
|
|
nRep->livei.unify(nVal->livei);
|
2018-11-11 15:52:33 -05:00
|
|
|
nRep->degreeLimit = MIN2(nRep->degreeLimit, nVal->degreeLimit);
|
|
|
|
|
nRep->maxReg = MIN2(nRep->maxReg, nVal->maxReg);
|
2012-04-09 20:58:39 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
GCRA::coalesce(ArrayList& insns)
|
|
|
|
|
{
|
|
|
|
|
bool ret = doCoalesce(insns, JOIN_MASK_PHI);
|
|
|
|
|
if (!ret)
|
|
|
|
|
return false;
|
|
|
|
|
switch (func->getProgram()->getTarget()->getChipset() & ~0xf) {
|
|
|
|
|
case 0x50:
|
|
|
|
|
case 0x80:
|
|
|
|
|
case 0x90:
|
|
|
|
|
case 0xa0:
|
|
|
|
|
ret = doCoalesce(insns, JOIN_MASK_UNION | JOIN_MASK_TEX);
|
|
|
|
|
break;
|
|
|
|
|
case 0xc0:
|
|
|
|
|
case 0xd0:
|
|
|
|
|
case 0xe0:
|
2013-12-06 09:09:42 +10:00
|
|
|
case 0xf0:
|
|
|
|
|
case 0x100:
|
2014-05-09 15:56:05 +10:00
|
|
|
case 0x110:
|
2016-02-16 07:56:44 +10:00
|
|
|
case 0x120:
|
2016-07-09 10:06:44 +10:00
|
|
|
case 0x130:
|
2020-06-07 09:52:35 +10:00
|
|
|
case 0x140:
|
2020-06-07 09:52:37 +10:00
|
|
|
case 0x160:
|
2022-05-30 23:39:59 +02:00
|
|
|
case 0x170:
|
2023-07-18 22:22:43 +02:00
|
|
|
case 0x190:
|
2012-04-09 20:58:39 +02:00
|
|
|
ret = doCoalesce(insns, JOIN_MASK_UNION);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!ret)
|
|
|
|
|
return false;
|
|
|
|
|
return doCoalesce(insns, JOIN_MASK_MOV);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint8_t makeCompMask(int compSize, int base, int size)
|
|
|
|
|
{
|
|
|
|
|
uint8_t m = ((1 << size) - 1) << base;
|
|
|
|
|
|
|
|
|
|
switch (compSize) {
|
|
|
|
|
case 1:
|
|
|
|
|
return 0xff;
|
|
|
|
|
case 2:
|
|
|
|
|
m |= (m << 2);
|
|
|
|
|
return (m << 4) | m;
|
|
|
|
|
case 3:
|
|
|
|
|
case 4:
|
|
|
|
|
return (m << 4) | m;
|
|
|
|
|
default:
|
|
|
|
|
assert(compSize <= 8);
|
|
|
|
|
return m;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GCRA::makeCompound(Instruction *insn, bool split)
|
|
|
|
|
{
|
|
|
|
|
LValue *rep = (split ? insn->getSrc(0) : insn->getDef(0))->asLValue();
|
|
|
|
|
|
|
|
|
|
if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC) {
|
|
|
|
|
INFO("makeCompound(split = %i): ", split);
|
|
|
|
|
insn->print();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const unsigned int size = getNode(rep)->colors;
|
|
|
|
|
unsigned int base = 0;
|
|
|
|
|
|
|
|
|
|
if (!rep->compound)
|
|
|
|
|
rep->compMask = 0xff;
|
|
|
|
|
rep->compound = 1;
|
|
|
|
|
|
|
|
|
|
for (int c = 0; split ? insn->defExists(c) : insn->srcExists(c); ++c) {
|
|
|
|
|
LValue *val = (split ? insn->getDef(c) : insn->getSrc(c))->asLValue();
|
|
|
|
|
|
|
|
|
|
val->compound = 1;
|
|
|
|
|
if (!val->compMask)
|
|
|
|
|
val->compMask = 0xff;
|
|
|
|
|
val->compMask &= makeCompMask(size, base, getNode(val)->colors);
|
|
|
|
|
assert(val->compMask);
|
|
|
|
|
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "compound: %%%i:%02x <- %%%i:%02x\n",
|
|
|
|
|
rep->id, rep->compMask, val->id, val->compMask);
|
|
|
|
|
|
|
|
|
|
base += getNode(val)->colors;
|
|
|
|
|
}
|
|
|
|
|
assert(base == size);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
bool
|
2012-04-09 20:58:39 +02:00
|
|
|
GCRA::doCoalesce(ArrayList& insns, unsigned int mask)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2023-02-14 18:05:21 +01:00
|
|
|
int c;
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2023-02-14 18:05:21 +01:00
|
|
|
for (unsigned int n = 0; n < insns.getSize(); ++n) {
|
2011-09-14 16:18:23 +02:00
|
|
|
Instruction *i;
|
2012-04-09 20:58:39 +02:00
|
|
|
Instruction *insn = reinterpret_cast<Instruction *>(insns.get(n));
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
switch (insn->op) {
|
|
|
|
|
case OP_PHI:
|
|
|
|
|
if (!(mask & JOIN_MASK_PHI))
|
|
|
|
|
break;
|
|
|
|
|
for (c = 0; insn->srcExists(c); ++c)
|
2012-04-09 20:58:39 +02:00
|
|
|
if (!coalesceValues(insn->getDef(0), insn->getSrc(c), false)) {
|
|
|
|
|
// this is bad
|
2011-09-14 16:18:23 +02:00
|
|
|
ERROR("failed to coalesce phi operands\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case OP_UNION:
|
2012-04-09 20:58:39 +02:00
|
|
|
case OP_MERGE:
|
2011-09-14 16:18:23 +02:00
|
|
|
if (!(mask & JOIN_MASK_UNION))
|
|
|
|
|
break;
|
|
|
|
|
for (c = 0; insn->srcExists(c); ++c)
|
2012-04-09 20:58:39 +02:00
|
|
|
coalesceValues(insn->getDef(0), insn->getSrc(c), true);
|
|
|
|
|
if (insn->op == OP_MERGE) {
|
|
|
|
|
merges.push_back(insn);
|
|
|
|
|
if (insn->srcExists(1))
|
|
|
|
|
makeCompound(insn, false);
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
break;
|
2012-04-09 20:58:39 +02:00
|
|
|
case OP_SPLIT:
|
|
|
|
|
if (!(mask & JOIN_MASK_UNION))
|
2011-09-14 16:18:23 +02:00
|
|
|
break;
|
2012-04-09 20:58:39 +02:00
|
|
|
splits.push_back(insn);
|
|
|
|
|
for (c = 0; insn->defExists(c); ++c)
|
|
|
|
|
coalesceValues(insn->getSrc(0), insn->getDef(c), true);
|
|
|
|
|
makeCompound(insn, true);
|
2011-09-14 16:18:23 +02:00
|
|
|
break;
|
|
|
|
|
case OP_MOV:
|
|
|
|
|
if (!(mask & JOIN_MASK_MOV))
|
|
|
|
|
break;
|
2012-03-29 21:18:24 +02:00
|
|
|
i = NULL;
|
|
|
|
|
if (!insn->getDef(0)->uses.empty())
|
2014-07-08 04:19:13 +02:00
|
|
|
i = (*insn->getDef(0)->uses.begin())->getInsn();
|
2012-01-07 21:00:51 +01:00
|
|
|
// if this is a contraint-move there will only be a single use
|
2012-04-09 20:58:39 +02:00
|
|
|
if (i && i->op == OP_MERGE) // do we really still need this ?
|
2012-01-07 21:00:51 +01:00
|
|
|
break;
|
2011-09-14 16:18:23 +02:00
|
|
|
i = insn->getSrc(0)->getUniqueInsn();
|
2012-04-09 20:58:39 +02:00
|
|
|
if (i && !i->constrainedDefs()) {
|
nv50/ir/ra: Fix copying compound for moves
In order to reduce moves when coalescing multiple registers into a
larger register, RA will try to coalesce MERGE instructions with their
definitions. For example, for something like this in GLSL:
uint a = ...;
uint b = ...;
uint64 x = packUint2x32(a, b);
The compiler will try to coalesce x with a and b, in the same way as
something like:
uint a = ...;
uint b = ...;
...
uint x = phi(a, b);
with the crucial difference that the definitions of a and b only clobber
part of the register, instead of the whole thing. This information is
carried through the compound flag and compMask bitmask. If compound is
set, then the value has been coalesced in such a way that not all the
defs clobber the entire register. The compMask bitmask describes which
subregister each def clobbers, although it does it in a slightly
convoluted way. It's an invariant that once compound is set on one def,
it must be set for all the defs in a given coalesced value.
In more detail, the constraints pass will first create extra moves:
uint a = ...;
uint b = ...;
uint a' = a;
uint b' = b;
uint64 x = packUint2x32(a', b');
and then RA will merge values involved in MERGE/SPLIT instructions,
merging x with a' and b' and making the combined value compound -- this
is relatively simple, and will always succeed since we just created a'
and b', so they never interfere with x, and x has no other definitions,
since we haven't started coalescing moves yet. Basically, we just replaced
the MERGE instruction with an equivalent sequence of partial writes to the
destination. The tricky part comes when we try to merge a' with a
and b' with b. We need to transfer the compound information from a' to a
and b' to b, which copyCompound() does, but we also need to transfer it
to any defs coalesced with a and b, which the code failed to do. Similarly,
if x is the argument to a phi instruction, then when we try to merge it
with other arguments to the same phi by coalescing moves, we'd have
problems guaranteeing that all the other merged defs stay up-to-date.
One tricky part of fixing this is that in order to properly propagate
the information from a' to a, we need to do it before the defs for a and
a' are merged in coalesceValues(), since we need to know which defs are
merged with a but not a' -- after coalesceValues() returns, all the defs
have been combined, so we don't know which is which. I took the approach
of calling copyCompound() inside coalesceValues(), instead of
afterwards.
v2: (mhenning) This now loops over mergedDefs in copyCompound, to update
it for changes made in bcf6a9ec
Cc: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: Karol Herbst <kherbst@redhat.com>
Tested-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17115>
2018-01-08 19:25:01 -05:00
|
|
|
coalesceValues(insn->getDef(0), insn->getSrc(0), false);
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
break;
|
|
|
|
|
case OP_TEX:
|
|
|
|
|
case OP_TXB:
|
|
|
|
|
case OP_TXL:
|
|
|
|
|
case OP_TXF:
|
|
|
|
|
case OP_TXQ:
|
|
|
|
|
case OP_TXD:
|
|
|
|
|
case OP_TXG:
|
2014-05-13 01:31:20 -04:00
|
|
|
case OP_TXLQ:
|
2011-09-14 16:18:23 +02:00
|
|
|
case OP_TEXCSAA:
|
2014-05-13 01:31:20 -04:00
|
|
|
case OP_TEXPREP:
|
2011-09-14 16:18:23 +02:00
|
|
|
if (!(mask & JOIN_MASK_TEX))
|
|
|
|
|
break;
|
2012-04-09 20:58:39 +02:00
|
|
|
for (c = 0; insn->srcExists(c) && c != insn->predSrc; ++c)
|
|
|
|
|
coalesceValues(insn->getDef(c), insn->getSrc(c), true);
|
2011-09-14 16:18:23 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-04-09 20:58:39 +02:00
|
|
|
GCRA::RIG_Node::addInterference(RIG_Node *node)
|
|
|
|
|
{
|
|
|
|
|
this->degree += relDegree[node->colors][colors];
|
|
|
|
|
node->degree += relDegree[colors][node->colors];
|
|
|
|
|
|
|
|
|
|
this->attach(node, Graph::Edge::CROSS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GCRA::RIG_Node::addRegPreference(RIG_Node *node)
|
|
|
|
|
{
|
|
|
|
|
prefRegs.push_back(node);
|
|
|
|
|
}
|
|
|
|
|
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
GCRA::GCRA(Function *fn, SpillCodeInserter& spill, MergedDefs& mergedDefs) :
|
2020-11-09 19:48:04 -08:00
|
|
|
nodes(NULL),
|
|
|
|
|
nodeCount(0),
|
2012-04-09 20:58:39 +02:00
|
|
|
func(fn),
|
|
|
|
|
regs(fn->getProgram()->getTarget()),
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
spill(spill),
|
|
|
|
|
mergedDefs(mergedDefs)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
prog = func->getProgram();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GCRA::~GCRA()
|
|
|
|
|
{
|
|
|
|
|
if (nodes)
|
|
|
|
|
delete[] nodes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GCRA::checkList(std::list<RIG_Node *>& lst)
|
|
|
|
|
{
|
|
|
|
|
GCRA::RIG_Node *prev = NULL;
|
|
|
|
|
|
|
|
|
|
for (std::list<RIG_Node *>::iterator it = lst.begin();
|
|
|
|
|
it != lst.end();
|
|
|
|
|
++it) {
|
|
|
|
|
assert((*it)->getValue()->join == (*it)->getValue());
|
|
|
|
|
if (prev)
|
|
|
|
|
assert(prev->livei.begin() <= (*it)->livei.begin());
|
|
|
|
|
prev = *it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GCRA::insertOrderedTail(std::list<RIG_Node *>& list, RIG_Node *node)
|
|
|
|
|
{
|
|
|
|
|
if (node->livei.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
// only the intervals of joined values don't necessarily arrive in order
|
|
|
|
|
std::list<RIG_Node *>::iterator prev, it;
|
|
|
|
|
for (it = list.end(); it != list.begin(); it = prev) {
|
|
|
|
|
prev = it;
|
|
|
|
|
--prev;
|
|
|
|
|
if ((*prev)->livei.begin() <= node->livei.begin())
|
2011-09-14 16:18:23 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
list.insert(it, node);
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
GCRA::buildRIG(ArrayList& insns)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
std::list<RIG_Node *> values, active;
|
|
|
|
|
|
|
|
|
|
for (std::deque<ValueDef>::iterator it = func->ins.begin();
|
|
|
|
|
it != func->ins.end(); ++it)
|
|
|
|
|
insertOrderedTail(values, getNode(it->get()->asLValue()));
|
|
|
|
|
|
2023-02-14 18:05:21 +01:00
|
|
|
for (unsigned int i = 0; i < insns.getSize(); ++i) {
|
2012-04-09 20:58:39 +02:00
|
|
|
Instruction *insn = reinterpret_cast<Instruction *>(insns.get(i));
|
|
|
|
|
for (int d = 0; insn->defExists(d); ++d)
|
2020-07-14 22:32:47 +02:00
|
|
|
if (insn->getDef(d)->reg.file <= LAST_REGISTER_FILE &&
|
|
|
|
|
insn->getDef(d)->rep() == insn->getDef(d))
|
2012-04-09 20:58:39 +02:00
|
|
|
insertOrderedTail(values, getNode(insn->getDef(d)->asLValue()));
|
|
|
|
|
}
|
|
|
|
|
checkList(values);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
while (!values.empty()) {
|
|
|
|
|
RIG_Node *cur = values.front();
|
|
|
|
|
|
|
|
|
|
for (std::list<RIG_Node *>::iterator it = active.begin();
|
2012-04-30 15:19:40 +02:00
|
|
|
it != active.end();) {
|
2012-04-09 20:58:39 +02:00
|
|
|
RIG_Node *node = *it;
|
|
|
|
|
|
|
|
|
|
if (node->livei.end() <= cur->livei.begin()) {
|
|
|
|
|
it = active.erase(it);
|
2012-04-30 15:19:40 +02:00
|
|
|
} else {
|
|
|
|
|
if (node->f == cur->f && node->livei.overlaps(cur->livei))
|
|
|
|
|
cur->addInterference(node);
|
|
|
|
|
++it;
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
values.pop_front();
|
|
|
|
|
active.push_back(cur);
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2012-04-09 20:58:39 +02:00
|
|
|
GCRA::calculateSpillWeights()
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
for (unsigned int i = 0; i < nodeCount; ++i) {
|
|
|
|
|
RIG_Node *const n = &nodes[i];
|
|
|
|
|
if (!nodes[i].colors || nodes[i].livei.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
if (nodes[i].reg >= 0) {
|
|
|
|
|
// update max reg
|
|
|
|
|
regs.occupy(n->f, n->reg, n->colors);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
LValue *val = nodes[i].getValue();
|
2011-11-15 17:24:18 +01:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
if (!val->noSpill) {
|
|
|
|
|
int rc = 0;
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
for (ValueDef *def : mergedDefs(val))
|
2020-01-15 20:37:27 +01:00
|
|
|
rc += def->get()->refCount();
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
nodes[i].weight =
|
|
|
|
|
(float)rc * (float)rc / (float)nodes[i].livei.extent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nodes[i].degree < nodes[i].degreeLimit) {
|
|
|
|
|
int l = 0;
|
|
|
|
|
if (val->reg.size > 4)
|
|
|
|
|
l = 1;
|
|
|
|
|
DLLIST_ADDHEAD(&lo[l], &nodes[i]);
|
|
|
|
|
} else {
|
|
|
|
|
DLLIST_ADDHEAD(&hi, &nodes[i]);
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC)
|
|
|
|
|
printNodeInfo();
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
GCRA::simplifyEdge(RIG_Node *a, RIG_Node *b)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
bool move = b->degree >= b->degreeLimit;
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC,
|
|
|
|
|
"edge: (%%%i, deg %u/%u) >-< (%%%i, deg %u/%u)\n",
|
|
|
|
|
a->getValue()->id, a->degree, a->degreeLimit,
|
|
|
|
|
b->getValue()->id, b->degree, b->degreeLimit);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
b->degree -= relDegree[a->colors][b->colors];
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
move = move && b->degree < b->degreeLimit;
|
|
|
|
|
if (move && !DLLIST_EMPTY(b)) {
|
|
|
|
|
int l = (b->getValue()->reg.size > 4) ? 1 : 0;
|
|
|
|
|
DLLIST_DEL(b);
|
|
|
|
|
DLLIST_ADDTAIL(&lo[l], b);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
GCRA::simplifyNode(RIG_Node *node)
|
|
|
|
|
{
|
|
|
|
|
for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next())
|
|
|
|
|
simplifyEdge(node, RIG_Node::get(ei));
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
for (Graph::EdgeIterator ei = node->incident(); !ei.end(); ei.next())
|
|
|
|
|
simplifyEdge(node, RIG_Node::get(ei));
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
DLLIST_DEL(node);
|
|
|
|
|
stack.push(node->getValue()->id);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "SIMPLIFY: pushed %%%i%s\n",
|
|
|
|
|
node->getValue()->id,
|
|
|
|
|
(node->degree < node->degreeLimit) ? "" : "(spill)");
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-03 18:55:09 +02:00
|
|
|
bool
|
2012-04-09 20:58:39 +02:00
|
|
|
GCRA::simplify()
|
|
|
|
|
{
|
|
|
|
|
for (;;) {
|
|
|
|
|
if (!DLLIST_EMPTY(&lo[0])) {
|
|
|
|
|
do {
|
|
|
|
|
simplifyNode(lo[0].next);
|
|
|
|
|
} while (!DLLIST_EMPTY(&lo[0]));
|
|
|
|
|
} else
|
|
|
|
|
if (!DLLIST_EMPTY(&lo[1])) {
|
|
|
|
|
simplifyNode(lo[1].next);
|
|
|
|
|
} else
|
|
|
|
|
if (!DLLIST_EMPTY(&hi)) {
|
|
|
|
|
RIG_Node *best = hi.next;
|
2018-11-11 15:52:33 -05:00
|
|
|
unsigned bestMaxReg = best->maxReg;
|
2012-04-09 20:58:39 +02:00
|
|
|
float bestScore = best->weight / (float)best->degree;
|
2018-11-11 15:52:33 -05:00
|
|
|
// Spill candidate. First go through the ones with the highest max
|
|
|
|
|
// register, then the ones with lower. That way the ones with the
|
|
|
|
|
// lowest requirement will be allocated first, since it's a stack.
|
2012-04-09 20:58:39 +02:00
|
|
|
for (RIG_Node *it = best->next; it != &hi; it = it->next) {
|
|
|
|
|
float score = it->weight / (float)it->degree;
|
2018-11-11 15:52:33 -05:00
|
|
|
if (score < bestScore || it->maxReg > bestMaxReg) {
|
2012-04-09 20:58:39 +02:00
|
|
|
best = it;
|
|
|
|
|
bestScore = score;
|
2018-11-11 15:52:33 -05:00
|
|
|
bestMaxReg = it->maxReg;
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
if (isinf(bestScore)) {
|
|
|
|
|
ERROR("no viable spill candidates left\n");
|
2016-10-03 18:55:09 +02:00
|
|
|
return false;
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
simplifyNode(best);
|
|
|
|
|
} else {
|
2016-10-03 18:55:09 +02:00
|
|
|
return true;
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GCRA::checkInterference(const RIG_Node *node, Graph::EdgeIterator& ei)
|
|
|
|
|
{
|
|
|
|
|
const RIG_Node *intf = RIG_Node::get(ei);
|
|
|
|
|
|
|
|
|
|
if (intf->reg < 0)
|
|
|
|
|
return;
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
LValue *vA = node->getValue();
|
|
|
|
|
LValue *vB = intf->getValue();
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
const uint8_t intfMask = ((1 << intf->colors) - 1) << (intf->reg & 7);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
if (vA->compound | vB->compound) {
|
|
|
|
|
// NOTE: this only works for >aligned< register tuples !
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
for (const ValueDef *D : mergedDefs(vA)) {
|
|
|
|
|
for (const ValueDef *d : mergedDefs(vB)) {
|
2020-01-15 20:37:27 +01:00
|
|
|
const LValue *vD = D->get()->asLValue();
|
|
|
|
|
const LValue *vd = d->get()->asLValue();
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
if (!vD->livei.overlaps(vd->livei)) {
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "(%%%i) X (%%%i): no overlap\n",
|
|
|
|
|
vD->id, vd->id);
|
|
|
|
|
continue;
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
uint8_t mask = vD->compound ? vD->compMask : ~0;
|
|
|
|
|
if (vd->compound) {
|
|
|
|
|
assert(vB->compound);
|
|
|
|
|
mask &= vd->compMask & vB->compMask;
|
|
|
|
|
} else {
|
|
|
|
|
mask &= intfMask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC,
|
|
|
|
|
"(%%%i)%02x X (%%%i)%02x & %02x: $r%i.%02x\n",
|
|
|
|
|
vD->id,
|
|
|
|
|
vD->compound ? vD->compMask : 0xff,
|
|
|
|
|
vd->id,
|
|
|
|
|
vd->compound ? vd->compMask : intfMask,
|
|
|
|
|
vB->compMask, intf->reg & ~7, mask);
|
|
|
|
|
if (mask)
|
|
|
|
|
regs.occupyMask(node->f, intf->reg & ~7, mask);
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC,
|
|
|
|
|
"(%%%i) X (%%%i): $r%i + %u\n",
|
|
|
|
|
vA->id, vB->id, intf->reg, intf->colors);
|
2013-02-06 17:14:55 +01:00
|
|
|
regs.occupy(node->f, intf->reg, intf->colors);
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
bool
|
|
|
|
|
GCRA::selectRegisters()
|
|
|
|
|
{
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "\nSELECT phase\n");
|
|
|
|
|
|
|
|
|
|
while (!stack.empty()) {
|
|
|
|
|
RIG_Node *node = &nodes[stack.top()];
|
|
|
|
|
stack.pop();
|
|
|
|
|
|
|
|
|
|
regs.reset(node->f);
|
|
|
|
|
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "\nNODE[%%%i, %u colors]\n",
|
|
|
|
|
node->getValue()->id, node->colors);
|
|
|
|
|
|
|
|
|
|
for (Graph::EdgeIterator ei = node->outgoing(); !ei.end(); ei.next())
|
|
|
|
|
checkInterference(node, ei);
|
|
|
|
|
for (Graph::EdgeIterator ei = node->incident(); !ei.end(); ei.next())
|
|
|
|
|
checkInterference(node, ei);
|
|
|
|
|
|
|
|
|
|
if (!node->prefRegs.empty()) {
|
|
|
|
|
for (std::list<RIG_Node *>::const_iterator it = node->prefRegs.begin();
|
|
|
|
|
it != node->prefRegs.end();
|
|
|
|
|
++it) {
|
|
|
|
|
if ((*it)->reg >= 0 &&
|
2013-02-06 17:14:55 +01:00
|
|
|
regs.testOccupy(node->f, (*it)->reg, node->colors)) {
|
2012-04-09 20:58:39 +02:00
|
|
|
node->reg = (*it)->reg;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (node->reg >= 0)
|
|
|
|
|
continue;
|
|
|
|
|
LValue *lval = node->getValue();
|
|
|
|
|
if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC)
|
2016-05-31 00:33:19 -04:00
|
|
|
regs.print(node->f);
|
2018-11-11 15:52:33 -05:00
|
|
|
bool ret = regs.assign(node->reg, node->f, node->colors, node->maxReg);
|
2012-04-09 20:58:39 +02:00
|
|
|
if (ret) {
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "assigned reg %i\n", node->reg);
|
|
|
|
|
lval->compMask = node->getCompMask();
|
|
|
|
|
} else {
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "must spill: %%%i (size %u)\n",
|
|
|
|
|
lval->id, lval->reg.size);
|
|
|
|
|
Symbol *slot = NULL;
|
|
|
|
|
if (lval->reg.file == FILE_GPR)
|
|
|
|
|
slot = spill.assignSlot(node->livei, lval->reg.size);
|
|
|
|
|
mustSpill.push_back(ValuePair(lval, slot));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!mustSpill.empty())
|
|
|
|
|
return false;
|
|
|
|
|
for (unsigned int i = 0; i < nodeCount; ++i) {
|
|
|
|
|
LValue *lval = nodes[i].getValue();
|
|
|
|
|
if (nodes[i].reg >= 0 && nodes[i].colors > 0)
|
|
|
|
|
lval->reg.data.id =
|
|
|
|
|
regs.unitsToId(nodes[i].f, nodes[i].reg, lval->reg.size);
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2012-04-09 20:58:39 +02:00
|
|
|
GCRA::allocateRegisters(ArrayList& insns)
|
2011-09-14 16:18:23 +02:00
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
bool ret;
|
|
|
|
|
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC,
|
|
|
|
|
"allocateRegisters to %u instructions\n", insns.getSize());
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
nodeCount = func->allLValues.getSize();
|
|
|
|
|
nodes = new RIG_Node[nodeCount];
|
|
|
|
|
if (!nodes)
|
|
|
|
|
return false;
|
|
|
|
|
for (unsigned int i = 0; i < nodeCount; ++i) {
|
|
|
|
|
LValue *lval = reinterpret_cast<LValue *>(func->allLValues.get(i));
|
|
|
|
|
if (lval) {
|
|
|
|
|
nodes[i].init(regs, lval);
|
|
|
|
|
RIG.insert(&nodes[i]);
|
2015-12-08 18:46:34 -05:00
|
|
|
|
2018-03-27 19:10:34 +02:00
|
|
|
if (lval->inFile(FILE_GPR) && lval->getInsn() != NULL) {
|
2015-12-08 18:46:34 -05:00
|
|
|
Instruction *insn = lval->getInsn();
|
2018-03-27 19:10:34 +02:00
|
|
|
if (insn->op != OP_MAD && insn->op != OP_FMA && insn->op != OP_SAD)
|
|
|
|
|
continue;
|
|
|
|
|
// For both of the cases below, we only want to add the preference
|
|
|
|
|
// if all arguments are in registers.
|
|
|
|
|
if (insn->src(0).getFile() != FILE_GPR ||
|
|
|
|
|
insn->src(1).getFile() != FILE_GPR ||
|
|
|
|
|
insn->src(2).getFile() != FILE_GPR)
|
|
|
|
|
continue;
|
|
|
|
|
if (prog->getTarget()->getChipset() < 0xc0) {
|
|
|
|
|
// Outputting a flag is not supported with short encodings nor
|
|
|
|
|
// with immediate arguments.
|
|
|
|
|
// See handleMADforNV50.
|
|
|
|
|
if (insn->flagsDef >= 0)
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
// We can only fold immediate arguments if dst == src2. This
|
|
|
|
|
// only matters if one of the first two arguments is an
|
|
|
|
|
// immediate. This form is also only supported for floats.
|
|
|
|
|
// See handleMADforNVC0.
|
|
|
|
|
ImmediateValue imm;
|
|
|
|
|
if (insn->dType != TYPE_F32)
|
|
|
|
|
continue;
|
|
|
|
|
if (!insn->src(0).getImmediate(imm) &&
|
|
|
|
|
!insn->src(1).getImmediate(imm))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nodes[i].addRegPreference(getNode(insn->getSrc(2)->asLValue()));
|
2015-12-08 18:46:34 -05:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
// coalesce first, we use only 1 RIG node for a group of joined values
|
|
|
|
|
ret = coalesce(insns);
|
|
|
|
|
if (!ret)
|
|
|
|
|
goto out;
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
if (func->getProgram()->dbgFlags & NV50_IR_DEBUG_REG_ALLOC)
|
|
|
|
|
func->printLiveIntervals();
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
buildRIG(insns);
|
|
|
|
|
calculateSpillWeights();
|
2016-10-03 18:55:09 +02:00
|
|
|
ret = simplify();
|
|
|
|
|
if (!ret)
|
|
|
|
|
goto out;
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
ret = selectRegisters();
|
|
|
|
|
if (!ret) {
|
|
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC,
|
|
|
|
|
"selectRegisters failed, inserting spill code ...\n");
|
|
|
|
|
regs.reset(FILE_GPR, true);
|
|
|
|
|
spill.run(mustSpill);
|
|
|
|
|
if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC)
|
|
|
|
|
func->print();
|
|
|
|
|
} else {
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
mergedDefs.merge();
|
2012-04-30 15:22:27 +02:00
|
|
|
prog->maxGPR = std::max(prog->maxGPR, regs.getMaxAssigned(FILE_GPR));
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
cleanup(ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GCRA::cleanup(const bool success)
|
|
|
|
|
{
|
|
|
|
|
mustSpill.clear();
|
|
|
|
|
|
|
|
|
|
for (ArrayList::Iterator it = func->allLValues.iterator();
|
|
|
|
|
!it.end(); it.next()) {
|
|
|
|
|
LValue *lval = reinterpret_cast<LValue *>(it.get());
|
|
|
|
|
|
|
|
|
|
lval->livei.clear();
|
|
|
|
|
|
|
|
|
|
lval->compound = 0;
|
|
|
|
|
lval->compMask = 0;
|
|
|
|
|
|
|
|
|
|
if (lval->join == lval)
|
|
|
|
|
continue;
|
|
|
|
|
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
if (success)
|
2012-04-09 20:58:39 +02:00
|
|
|
lval->reg.data.id = lval->join->reg.data.id;
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
else
|
2012-04-09 20:58:39 +02:00
|
|
|
lval->join = lval;
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
if (success)
|
|
|
|
|
resolveSplitsAndMerges();
|
|
|
|
|
splits.clear(); // avoid duplicate entries on next coalesce pass
|
|
|
|
|
merges.clear();
|
|
|
|
|
|
|
|
|
|
delete[] nodes;
|
|
|
|
|
nodes = NULL;
|
2016-01-26 14:36:04 +01:00
|
|
|
hi.next = hi.prev = &hi;
|
|
|
|
|
lo[0].next = lo[0].prev = &lo[0];
|
|
|
|
|
lo[1].next = lo[1].prev = &lo[1];
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Symbol *
|
2013-01-12 17:37:34 +01:00
|
|
|
SpillCodeInserter::assignSlot(const Interval &livei, const unsigned int size)
|
2012-04-09 20:58:39 +02:00
|
|
|
{
|
2023-05-12 22:54:40 -04:00
|
|
|
int32_t address = align(stackSize + func->tlsBase, size);
|
|
|
|
|
|
|
|
|
|
Symbol *sym = new_Symbol(func->getProgram(), FILE_MEMORY_LOCAL);
|
|
|
|
|
sym->setAddress(NULL, address);
|
|
|
|
|
sym->reg.size = size;
|
|
|
|
|
|
|
|
|
|
stackSize = address + size - func->tlsBase;
|
|
|
|
|
|
|
|
|
|
return sym;
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2014-02-19 04:00:34 +01:00
|
|
|
Value *
|
|
|
|
|
SpillCodeInserter::offsetSlot(Value *base, const LValue *lval)
|
2014-02-08 19:32:54 +01:00
|
|
|
{
|
2014-02-19 04:00:34 +01:00
|
|
|
if (!lval->compound || (lval->compMask & 0x1))
|
2014-02-08 19:32:54 +01:00
|
|
|
return base;
|
2014-02-19 04:00:34 +01:00
|
|
|
Value *slot = cloneShallow(func, base);
|
2014-02-08 19:32:54 +01:00
|
|
|
|
2021-04-24 23:27:06 +02:00
|
|
|
const unsigned int unit = func->getProgram()->getTarget()->getFileUnit(lval->reg.file);
|
|
|
|
|
slot->reg.data.offset += (ffs(lval->compMask) - 1) << unit;
|
|
|
|
|
assert((slot->reg.data.offset % lval->reg.size) == 0);
|
2014-02-08 19:32:54 +01:00
|
|
|
slot->reg.size = lval->reg.size;
|
|
|
|
|
|
|
|
|
|
return slot;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
SpillCodeInserter::spill(Instruction *defi, Value *slot, LValue *lval)
|
|
|
|
|
{
|
2014-02-08 19:32:54 +01:00
|
|
|
const DataType ty = typeOfSize(lval->reg.size);
|
|
|
|
|
|
2014-02-19 04:00:34 +01:00
|
|
|
slot = offsetSlot(slot, lval);
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
Instruction *st;
|
|
|
|
|
if (slot->reg.file == FILE_MEMORY_LOCAL) {
|
|
|
|
|
lval->noSpill = 1;
|
2015-04-18 15:00:45 -04:00
|
|
|
if (ty != TYPE_B96) {
|
|
|
|
|
st = new_Instruction(func, OP_STORE, ty);
|
|
|
|
|
st->setSrc(0, slot);
|
|
|
|
|
st->setSrc(1, lval);
|
|
|
|
|
} else {
|
|
|
|
|
st = new_Instruction(func, OP_SPLIT, ty);
|
|
|
|
|
st->setSrc(0, lval);
|
|
|
|
|
for (int d = 0; d < lval->reg.size / 4; ++d)
|
|
|
|
|
st->setDef(d, new_LValue(func, FILE_GPR));
|
|
|
|
|
|
|
|
|
|
for (int d = lval->reg.size / 4 - 1; d >= 0; --d) {
|
|
|
|
|
Value *tmp = cloneShallow(func, slot);
|
|
|
|
|
tmp->reg.size = 4;
|
|
|
|
|
tmp->reg.data.offset += 4 * d;
|
|
|
|
|
|
|
|
|
|
Instruction *s = new_Instruction(func, OP_STORE, TYPE_U32);
|
|
|
|
|
s->setSrc(0, tmp);
|
|
|
|
|
s->setSrc(1, st->getDef(d));
|
|
|
|
|
defi->bb->insertAfter(defi, s);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
} else {
|
|
|
|
|
st = new_Instruction(func, OP_CVT, ty);
|
|
|
|
|
st->setDef(0, slot);
|
|
|
|
|
st->setSrc(0, lval);
|
2015-11-25 23:36:23 -05:00
|
|
|
if (lval->reg.file == FILE_FLAGS)
|
|
|
|
|
st->flagsSrc = 0;
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
defi->bb->insertAfter(defi, st);
|
|
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
LValue *
|
|
|
|
|
SpillCodeInserter::unspill(Instruction *usei, LValue *lval, Value *slot)
|
|
|
|
|
{
|
2014-02-08 19:32:54 +01:00
|
|
|
const DataType ty = typeOfSize(lval->reg.size);
|
2012-04-09 20:58:39 +02:00
|
|
|
|
2014-02-19 04:00:34 +01:00
|
|
|
slot = offsetSlot(slot, lval);
|
2012-04-09 20:58:39 +02:00
|
|
|
lval = cloneShallow(func, lval);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
Instruction *ld;
|
|
|
|
|
if (slot->reg.file == FILE_MEMORY_LOCAL) {
|
|
|
|
|
lval->noSpill = 1;
|
2015-04-18 15:00:45 -04:00
|
|
|
if (ty != TYPE_B96) {
|
|
|
|
|
ld = new_Instruction(func, OP_LOAD, ty);
|
|
|
|
|
} else {
|
|
|
|
|
ld = new_Instruction(func, OP_MERGE, ty);
|
|
|
|
|
for (int d = 0; d < lval->reg.size / 4; ++d) {
|
|
|
|
|
Value *tmp = cloneShallow(func, slot);
|
|
|
|
|
LValue *val;
|
|
|
|
|
tmp->reg.size = 4;
|
|
|
|
|
tmp->reg.data.offset += 4 * d;
|
|
|
|
|
|
|
|
|
|
Instruction *l = new_Instruction(func, OP_LOAD, TYPE_U32);
|
|
|
|
|
l->setDef(0, (val = new_LValue(func, FILE_GPR)));
|
|
|
|
|
l->setSrc(0, tmp);
|
|
|
|
|
usei->bb->insertBefore(usei, l);
|
|
|
|
|
ld->setSrc(d, val);
|
|
|
|
|
val->noSpill = 1;
|
|
|
|
|
}
|
|
|
|
|
ld->setDef(0, lval);
|
|
|
|
|
usei->bb->insertBefore(usei, ld);
|
|
|
|
|
return lval;
|
|
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
} else {
|
|
|
|
|
ld = new_Instruction(func, OP_CVT, ty);
|
|
|
|
|
}
|
|
|
|
|
ld->setDef(0, lval);
|
|
|
|
|
ld->setSrc(0, slot);
|
2015-11-25 23:36:23 -05:00
|
|
|
if (lval->reg.file == FILE_FLAGS)
|
|
|
|
|
ld->flagsDef = 0;
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
usei->bb->insertBefore(usei, ld);
|
|
|
|
|
return lval;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 23:25:54 -05:00
|
|
|
static bool
|
|
|
|
|
value_cmp(ValueRef *a, ValueRef *b) {
|
|
|
|
|
Instruction *ai = a->getInsn(), *bi = b->getInsn();
|
|
|
|
|
if (ai->bb != bi->bb)
|
|
|
|
|
return ai->bb->getId() < bi->bb->getId();
|
|
|
|
|
return ai->serial < bi->serial;
|
|
|
|
|
}
|
2014-02-08 19:32:54 +01:00
|
|
|
|
|
|
|
|
// For each value that is to be spilled, go through all its definitions.
|
|
|
|
|
// A value can have multiple definitions if it has been coalesced before.
|
|
|
|
|
// For each definition, first go through all its uses and insert an unspill
|
|
|
|
|
// instruction before it, then replace the use with the temporary register.
|
|
|
|
|
// Unspill can be either a load from memory or simply a move to another
|
|
|
|
|
// register file.
|
|
|
|
|
// For "Pseudo" instructions (like PHI, SPLIT, MERGE) we can erase the use
|
|
|
|
|
// if we have spilled to a memory location, or simply with the new register.
|
|
|
|
|
// No load or conversion instruction should be needed.
|
2012-04-09 20:58:39 +02:00
|
|
|
bool
|
|
|
|
|
SpillCodeInserter::run(const std::list<ValuePair>& lst)
|
|
|
|
|
{
|
|
|
|
|
for (std::list<ValuePair>::const_iterator it = lst.begin(); it != lst.end();
|
|
|
|
|
++it) {
|
|
|
|
|
LValue *lval = it->first->asLValue();
|
|
|
|
|
Symbol *mem = it->second ? it->second->asSym() : NULL;
|
|
|
|
|
|
2014-09-24 21:45:07 -04:00
|
|
|
// Keep track of which instructions to delete later. Deleting them
|
|
|
|
|
// inside the loop is unsafe since a single instruction may have
|
|
|
|
|
// multiple destinations that all need to be spilled (like OP_SPLIT).
|
2022-06-18 16:45:53 -04:00
|
|
|
std::unordered_set<Instruction *> to_del;
|
2014-09-24 21:45:07 -04:00
|
|
|
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
std::list<ValueDef *> &defs = mergedDefs(lval);
|
|
|
|
|
for (Value::DefIterator d = defs.begin(); d != defs.end();
|
2012-04-09 20:58:39 +02:00
|
|
|
++d) {
|
|
|
|
|
Value *slot = mem ?
|
|
|
|
|
static_cast<Value *>(mem) : new_LValue(func, FILE_GPR);
|
|
|
|
|
Value *tmp = NULL;
|
|
|
|
|
Instruction *last = NULL;
|
|
|
|
|
|
|
|
|
|
LValue *dval = (*d)->get()->asLValue();
|
|
|
|
|
Instruction *defi = (*d)->getInsn();
|
|
|
|
|
|
2015-12-06 23:25:54 -05:00
|
|
|
// Sort all the uses by BB/instruction so that we don't unspill
|
|
|
|
|
// multiple times in a row, and also remove a source of
|
|
|
|
|
// non-determinism.
|
|
|
|
|
std::vector<ValueRef *> refs(dval->uses.begin(), dval->uses.end());
|
|
|
|
|
std::sort(refs.begin(), refs.end(), value_cmp);
|
|
|
|
|
|
2014-02-08 19:32:54 +01:00
|
|
|
// Unspill at each use *before* inserting spill instructions,
|
|
|
|
|
// we don't want to have the spill instructions in the use list here.
|
2015-12-06 23:25:54 -05:00
|
|
|
for (std::vector<ValueRef*>::const_iterator it = refs.begin();
|
|
|
|
|
it != refs.end(); ++it) {
|
|
|
|
|
ValueRef *u = *it;
|
2012-04-09 20:58:39 +02:00
|
|
|
Instruction *usei = u->getInsn();
|
|
|
|
|
assert(usei);
|
2014-02-08 19:32:54 +01:00
|
|
|
if (usei->isPseudo()) {
|
2012-04-09 20:58:39 +02:00
|
|
|
tmp = (slot->reg.file == FILE_MEMORY_LOCAL) ? NULL : slot;
|
|
|
|
|
last = NULL;
|
2015-12-06 23:25:54 -05:00
|
|
|
} else {
|
|
|
|
|
if (!last || (usei != last->next && usei != last))
|
|
|
|
|
tmp = unspill(usei, dval, slot);
|
2012-04-09 20:58:39 +02:00
|
|
|
last = usei;
|
|
|
|
|
}
|
|
|
|
|
u->set(tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(defi);
|
2014-02-08 19:32:54 +01:00
|
|
|
if (defi->isPseudo()) {
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
d = defs.erase(d);
|
2012-04-09 20:58:39 +02:00
|
|
|
--d;
|
|
|
|
|
if (slot->reg.file == FILE_MEMORY_LOCAL)
|
2014-09-24 21:45:07 -04:00
|
|
|
to_del.insert(defi);
|
2012-04-09 20:58:39 +02:00
|
|
|
else
|
|
|
|
|
defi->setDef(0, slot);
|
|
|
|
|
} else {
|
|
|
|
|
spill(defi, slot, dval);
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
|
2022-06-18 16:45:53 -04:00
|
|
|
for (std::unordered_set<Instruction *>::const_iterator it = to_del.begin();
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
it != to_del.end(); ++it) {
|
|
|
|
|
mergedDefs.removeDefsOfInstruction(*it);
|
2014-09-24 21:45:07 -04:00
|
|
|
delete_Instruction(func->getProgram(), *it);
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
stackBase = stackSize;
|
2011-09-14 16:18:23 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::exec()
|
|
|
|
|
{
|
2012-04-09 21:18:31 +02:00
|
|
|
for (IteratorRef it = prog->calls.iteratorDFS(false);
|
|
|
|
|
!it->end(); it->next()) {
|
|
|
|
|
func = Function::get(reinterpret_cast<Graph::Node *>(it->get()));
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
func->tlsBase = prog->tlsSize;
|
2011-09-14 16:18:23 +02:00
|
|
|
if (!execFunc())
|
|
|
|
|
return false;
|
2012-04-09 20:58:39 +02:00
|
|
|
prog->tlsSize += func->tlsSize;
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::execFunc()
|
|
|
|
|
{
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
MergedDefs mergedDefs;
|
2011-09-14 16:18:23 +02:00
|
|
|
InsertConstraintsPass insertConstr;
|
2012-03-29 23:23:53 +02:00
|
|
|
PhiMovesPass insertPhiMoves;
|
2011-09-14 16:18:23 +02:00
|
|
|
BuildIntervalsPass buildIntervals;
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
SpillCodeInserter insertSpills(func, mergedDefs);
|
2012-04-09 20:58:39 +02:00
|
|
|
|
nv50/ir/ra: fix memory corruption when spilling
When doing RA we end up with adding ValueDef references to Values across
all over the shader. This is all fine until we remove the Instruction
defining those Values, which happens when spilling values.
Instead of manipulating the values directly we should just track all
merged in defs in a seperate structure and remove stale references when
an instruction gets deleted in the spiller.
fixes following libasan report:
=================================================================
==612087==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150003ea380 at pc 0x7f1d12142fe9 bp 0x7fffca6fd120 sp 0x7fffca6fd110
READ of size 8 at 0x6150003ea380 thread T0
#0 0x7f1d12142fe8 in nv50_ir::ValueDef::get() const ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648
#1 0x7f1d12143c02 in nv50_ir::Value::getUniqueInsn() const ../src/gallium/drivers/nouveau/codegen/nv50_ir_inlines.h:229
#2 0x7f1d1221530d in nv50_ir::RegAlloc::BuildIntervalsPass::addLiveRange(nv50_ir::Value*, nv50_ir::BasicBlock const*, int) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:333
#3 0x7f1d1221872e in nv50_ir::RegAlloc::BuildIntervalsPass::visit(nv50_ir::BasicBlock*) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:686
#4 0x7f1d1215676c in nv50_ir::Pass::doRun(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:495
#5 0x7f1d121563ed in nv50_ir::Pass::run(nv50_ir::Function*, bool, bool) ../src/gallium/drivers/nouveau/codegen/nv50_ir_bb.cpp:477
#6 0x7f1d122262b8 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1910
#7 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#8 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#9 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#10 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#11 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#12 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#13 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#14 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#15 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#16 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#17 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#18 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#19 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#20 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#21 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#22 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#23 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
#24 0x7f1d17b8b4b5 in GOMP_parallel (/lib64/libgomp.so.1+0x124b5)
#25 0x4029e4 in main /home/kherbst/git/shader-db/run.c:765
#26 0x7f1d179b51a2 in __libc_start_main ../csu/libc-start.c:308
#27 0x402d1d in _start (/home/kherbst/git/shader-db/run+0x402d1d)
0x6150003ea380 is located 0 bytes inside of 504-byte region [0x6150003ea380,0x6150003ea578)
freed by thread T0 here:
#0 0x7f1d17e5d96f in operator delete(void*) (/usr/lib64/libasan.so.5.0.0+0x11096f)
#1 0x7f1d1214ec0f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::deallocate(nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/ext/new_allocator.h:128
#2 0x7f1d1214dc00 in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::deallocate(std::allocator<nv50_ir::ValueDef>&, nv50_ir::ValueDef*, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:470
#3 0x7f1d1214c5fb in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_deallocate_node(nv50_ir::ValueDef*) /usr/include/c++/9/bits/stl_deque.h:624
#4 0x7f1d121498c4 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_destroy_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) /usr/include/c++/9/bits/stl_deque.h:758
#5 0x7f1d1214704d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~_Deque_base() /usr/include/c++/9/bits/stl_deque.h:680
#6 0x7f1d12145371 in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::~deque() /usr/include/c++/9/bits/stl_deque.h:1069
#7 0x7f1d1213bc5b in nv50_ir::Instruction::~Instruction() ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:615
#8 0x7f1d1213fb2f in nv50_ir::Program::releaseInstruction(nv50_ir::Instruction*) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1148
#9 0x7f1d122250fb in nv50_ir::SpillCodeInserter::run(std::__cxx11::list<std::pair<nv50_ir::Value*, nv50_ir::Value*>, std::allocator<std::pair<nv50_ir::Value*, nv50_ir::Value*> > > const&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1830
#10 0x7f1d12221445 in nv50_ir::GCRA::allocateRegisters(nv50_ir::ArrayList&) ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1541
#11 0x7f1d122262e9 in nv50_ir::RegAlloc::execFunc() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1913
#12 0x7f1d122256b0 in nv50_ir::RegAlloc::exec() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1849
#13 0x7f1d12226f1e in nv50_ir::Program::registerAllocation() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ra.cpp:1970
#14 0x7f1d1214092a in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1275
#15 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#16 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#17 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#18 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#19 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#20 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#21 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#22 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#23 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#24 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#25 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#26 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#27 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#28 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
previously allocated by thread T0 here:
#0 0x7f1d17e5c9d7 in operator new(unsigned long) (/usr/lib64/libasan.so.5.0.0+0x10f9d7)
#1 0x7f1d1215046f in __gnu_cxx::new_allocator<nv50_ir::ValueDef>::allocate(unsigned long, void const*) /usr/include/c++/9/ext/new_allocator.h:114
#2 0x7f1d1214ebec in std::allocator_traits<std::allocator<nv50_ir::ValueDef> >::allocate(std::allocator<nv50_ir::ValueDef>&, unsigned long) /usr/include/c++/9/bits/alloc_traits.h:444
#3 0x7f1d1214dbd3 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_allocate_node() /usr/include/c++/9/bits/stl_deque.h:617
#4 0x7f1d1214c464 in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_create_nodes(nv50_ir::ValueDef**, nv50_ir::ValueDef**) (/home/kherbst/local/lib64/dri//nouveau_dri.so+0x829464)
#5 0x7f1d121495cd in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_M_initialize_map(unsigned long) /usr/include/c++/9/bits/stl_deque.h:716
#6 0x7f1d12146f7d in std::_Deque_base<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::_Deque_base() /usr/include/c++/9/bits/stl_deque.h:507
#7 0x7f1d1214518d in std::deque<nv50_ir::ValueDef, std::allocator<nv50_ir::ValueDef> >::deque() /usr/include/c++/9/bits/stl_deque.h:912
#8 0x7f1d1213b9c9 in nv50_ir::Instruction::Instruction(nv50_ir::Function*, nv50_ir::operation, nv50_ir::DataType) ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:605
#9 0x7f1d1224dd44 in nv50_ir::Function::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:385
#10 0x7f1d1224d381 in nv50_ir::Program::convertToSSA() ../src/gallium/drivers/nouveau/codegen/nv50_ir_ssa.cpp:310
#11 0x7f1d121407c0 in nv50_ir_generate_code ../src/gallium/drivers/nouveau/codegen/nv50_ir.cpp:1264
#12 0x7f1d1227461b in nvc0_program_translate ../src/gallium/drivers/nouveau/nvc0/nvc0_program.c:634
#13 0x7f1d12294b21 in nvc0_sp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:620
#14 0x7f1d12294d90 in nvc0_fp_state_create ../src/gallium/drivers/nouveau/nvc0/nvc0_state.c:661
#15 0x7f1d12ad4912 in st_create_fp_variant ../src/mesa/state_tracker/st_program.c:1498
#16 0x7f1d12ad4cd5 in st_get_fp_variant ../src/mesa/state_tracker/st_program.c:1525
#17 0x7f1d12ad8252 in st_precompile_shader_variant ../src/mesa/state_tracker/st_program.c:2053
#18 0x7f1d12c9c851 in st_program_string_notify ../src/mesa/state_tracker/st_cb_program.c:185
#19 0x7f1d12d17731 in st_link_tgsi ../src/mesa/state_tracker/st_glsl_to_tgsi.cpp:7441
#20 0x7f1d12cabaf0 in st_link_shader ../src/mesa/state_tracker/st_glsl_to_ir.cpp:175
#21 0x7f1d127c85ca in _mesa_glsl_link_shader ../src/mesa/program/ir_to_mesa.cpp:3186
#22 0x7f1d1252a9f7 in link_program ../src/mesa/main/shaderapi.c:1285
#23 0x7f1d1252a9f7 in link_program_error ../src/mesa/main/shaderapi.c:1384
#24 0x7f1d1252deb3 in _mesa_LinkProgram ../src/mesa/main/shaderapi.c:1876
#25 0x403e13 in main._omp_fn.0 /home/kherbst/git/shader-db/run.c:926
SUMMARY: AddressSanitizer: heap-use-after-free ../src/gallium/drivers/nouveau/codegen/nv50_ir.h:648 in nv50_ir::ValueDef::get() const
Shadow bytes around the buggy address:
0x0c2a80075420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c2a80075450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa
0x0c2a80075460: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c2a80075470:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075480: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a80075490: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c2a800754a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
0x0c2a800754b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c2a800754c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==612087==ABORTING
v2: full rework
v3: manage a full copy instead of recreating new lists on every access
Closes: #3066
Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5277>
2019-11-12 22:59:26 +01:00
|
|
|
GCRA gcra(func, insertSpills, mergedDefs);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
unsigned int i, retries;
|
2011-09-14 16:18:23 +02:00
|
|
|
bool ret;
|
|
|
|
|
|
2013-02-27 21:08:57 +01:00
|
|
|
if (!func->ins.empty()) {
|
|
|
|
|
// Insert a nop at the entry so inputs only used by the first instruction
|
|
|
|
|
// don't count as having an empty live range.
|
|
|
|
|
Instruction *nop = new_Instruction(func, OP_NOP, TYPE_NONE);
|
|
|
|
|
BasicBlock::get(func->cfg.getRoot())->insertHead(nop);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
ret = insertConstr.exec(func);
|
|
|
|
|
if (!ret)
|
|
|
|
|
goto out;
|
|
|
|
|
|
2012-03-29 23:23:53 +02:00
|
|
|
ret = insertPhiMoves.run(func);
|
|
|
|
|
if (!ret)
|
|
|
|
|
goto out;
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
// TODO: need to fix up spill slot usage ranges to support > 1 retry
|
|
|
|
|
for (retries = 0; retries < 3; ++retries) {
|
|
|
|
|
if (retries && (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC))
|
|
|
|
|
INFO("Retry: %i\n", retries);
|
|
|
|
|
if (prog->dbgFlags & NV50_IR_DEBUG_REG_ALLOC)
|
|
|
|
|
func->print();
|
|
|
|
|
|
|
|
|
|
// spilling to registers may add live ranges, need to rebuild everything
|
|
|
|
|
ret = true;
|
|
|
|
|
for (sequence = func->cfg.nextSequence(), i = 0;
|
|
|
|
|
ret && i <= func->loopNestingBound;
|
|
|
|
|
sequence = func->cfg.nextSequence(), ++i)
|
|
|
|
|
ret = buildLiveSets(BasicBlock::get(func->cfg.getRoot()));
|
2014-09-05 23:52:45 +02:00
|
|
|
// reset marker
|
|
|
|
|
for (ArrayList::Iterator bi = func->allBBlocks.iterator();
|
|
|
|
|
!bi.end(); bi.next())
|
|
|
|
|
BasicBlock::get(bi)->liveSet.marker = false;
|
2012-04-09 20:58:39 +02:00
|
|
|
if (!ret)
|
|
|
|
|
break;
|
|
|
|
|
func->orderInstructions(this->insns);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
ret = buildIntervals.run(func);
|
|
|
|
|
if (!ret)
|
|
|
|
|
break;
|
|
|
|
|
ret = gcra.allocateRegisters(insns);
|
|
|
|
|
if (ret)
|
|
|
|
|
break; // success
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
INFO_DBG(prog->dbgFlags, REG_ALLOC, "RegAlloc done: %i\n", ret);
|
2011-09-14 16:18:23 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
func->tlsSize = insertSpills.getStackSize();
|
2011-09-14 16:18:23 +02:00
|
|
|
out:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
// TODO: check if modifying Instruction::join here breaks anything
|
|
|
|
|
void
|
|
|
|
|
GCRA::resolveSplitsAndMerges()
|
|
|
|
|
{
|
|
|
|
|
for (std::list<Instruction *>::iterator it = splits.begin();
|
|
|
|
|
it != splits.end();
|
|
|
|
|
++it) {
|
|
|
|
|
Instruction *split = *it;
|
|
|
|
|
unsigned int reg = regs.idToBytes(split->getSrc(0));
|
|
|
|
|
for (int d = 0; split->defExists(d); ++d) {
|
|
|
|
|
Value *v = split->getDef(d);
|
|
|
|
|
v->reg.data.id = regs.bytesToId(v, reg);
|
|
|
|
|
v->join = v;
|
|
|
|
|
reg += v->reg.size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
splits.clear();
|
|
|
|
|
|
|
|
|
|
for (std::list<Instruction *>::iterator it = merges.begin();
|
|
|
|
|
it != merges.end();
|
|
|
|
|
++it) {
|
|
|
|
|
Instruction *merge = *it;
|
|
|
|
|
unsigned int reg = regs.idToBytes(merge->getDef(0));
|
|
|
|
|
for (int s = 0; merge->srcExists(s); ++s) {
|
|
|
|
|
Value *v = merge->getSrc(s);
|
|
|
|
|
v->reg.data.id = regs.bytesToId(v, reg);
|
|
|
|
|
v->join = v;
|
2014-07-17 00:30:40 -04:00
|
|
|
// If the value is defined by a phi/union node, we also need to
|
|
|
|
|
// perform the same fixup on that node's sources, since after RA
|
|
|
|
|
// their registers should be identical.
|
|
|
|
|
if (v->getInsn()->op == OP_PHI || v->getInsn()->op == OP_UNION) {
|
|
|
|
|
Instruction *phi = v->getInsn();
|
2016-10-10 16:57:50 -04:00
|
|
|
for (int phis = 0; phi->srcExists(phis); ++phis) {
|
2014-07-17 00:30:40 -04:00
|
|
|
phi->getSrc(phis)->join = v;
|
2016-10-10 16:57:50 -04:00
|
|
|
phi->getSrc(phis)->reg.data.id = v->reg.data.id;
|
|
|
|
|
}
|
2014-07-17 00:30:40 -04:00
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
reg += v->reg.size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
merges.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
bool
|
|
|
|
|
RegAlloc::InsertConstraintsPass::exec(Function *ir)
|
|
|
|
|
{
|
|
|
|
|
constrList.clear();
|
|
|
|
|
|
|
|
|
|
bool ret = run(ir, true, true);
|
|
|
|
|
if (ret)
|
|
|
|
|
ret = insertConstraintMoves();
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: make part of texture insn
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::textureMask(TexInstruction *tex)
|
|
|
|
|
{
|
|
|
|
|
Value *def[4];
|
|
|
|
|
int c, k, d;
|
|
|
|
|
uint8_t mask = 0;
|
|
|
|
|
|
|
|
|
|
for (d = 0, k = 0, c = 0; c < 4; ++c) {
|
|
|
|
|
if (!(tex->tex.mask & (1 << c)))
|
|
|
|
|
continue;
|
|
|
|
|
if (tex->getDef(k)->refCount()) {
|
|
|
|
|
mask |= 1 << c;
|
|
|
|
|
def[d++] = tex->getDef(k);
|
|
|
|
|
}
|
|
|
|
|
++k;
|
|
|
|
|
}
|
|
|
|
|
tex->tex.mask = mask;
|
|
|
|
|
|
|
|
|
|
for (c = 0; c < d; ++c)
|
|
|
|
|
tex->setDef(c, def[c]);
|
|
|
|
|
for (; c < 4; ++c)
|
|
|
|
|
tex->setDef(c, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add a dummy use of the pointer source of >= 8 byte loads after the load
|
|
|
|
|
// to prevent it from being assigned a register which overlapping the load's
|
|
|
|
|
// destination, which would produce random corruptions.
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::addHazard(Instruction *i, const ValueRef *src)
|
|
|
|
|
{
|
|
|
|
|
Instruction *hzd = new_Instruction(func, OP_NOP, TYPE_NONE);
|
|
|
|
|
hzd->setSrc(0, src->get());
|
|
|
|
|
i->bb->insertAfter(i, hzd);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
// b32 { %r0 %r1 %r2 %r3 } -> b128 %r0q
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::condenseDefs(Instruction *insn)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
2018-08-05 20:41:49 +02:00
|
|
|
for (n = 0; insn->defExists(n) && insn->def(n).getFile() == FILE_GPR; ++n);
|
|
|
|
|
condenseDefs(insn, 0, n - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::condenseDefs(Instruction *insn,
|
|
|
|
|
const int a, const int b)
|
|
|
|
|
{
|
|
|
|
|
uint8_t size = 0;
|
|
|
|
|
if (a >= b)
|
|
|
|
|
return;
|
|
|
|
|
for (int s = a; s <= b; ++s)
|
|
|
|
|
size += insn->getDef(s)->reg.size;
|
|
|
|
|
if (!size)
|
2012-04-09 20:58:39 +02:00
|
|
|
return;
|
2018-08-05 20:41:49 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
LValue *lval = new_LValue(func, FILE_GPR);
|
|
|
|
|
lval->reg.size = size;
|
|
|
|
|
|
|
|
|
|
Instruction *split = new_Instruction(func, OP_SPLIT, typeOfSize(size));
|
|
|
|
|
split->setSrc(0, lval);
|
2018-08-05 20:41:49 +02:00
|
|
|
for (int d = a; d <= b; ++d) {
|
|
|
|
|
split->setDef(d - a, insn->getDef(d));
|
2012-04-09 20:58:39 +02:00
|
|
|
insn->setDef(d, NULL);
|
|
|
|
|
}
|
2018-08-05 20:41:49 +02:00
|
|
|
insn->setDef(a, lval);
|
2012-04-09 20:58:39 +02:00
|
|
|
|
2018-08-05 20:41:49 +02:00
|
|
|
for (int k = a + 1, d = b + 1; insn->defExists(d); ++d, ++k) {
|
2012-04-09 20:58:39 +02:00
|
|
|
insn->setDef(k, insn->getDef(d));
|
|
|
|
|
insn->setDef(d, NULL);
|
|
|
|
|
}
|
|
|
|
|
// carry over predicate if any (mainly for OP_UNION uses)
|
|
|
|
|
split->setPredicate(insn->cc, insn->getPredicate());
|
|
|
|
|
|
|
|
|
|
insn->bb->insertAfter(insn, split);
|
|
|
|
|
constrList.push_back(split);
|
|
|
|
|
}
|
2018-08-05 20:41:49 +02:00
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::condenseSrcs(Instruction *insn,
|
|
|
|
|
const int a, const int b)
|
|
|
|
|
{
|
|
|
|
|
uint8_t size = 0;
|
|
|
|
|
if (a >= b)
|
|
|
|
|
return;
|
|
|
|
|
for (int s = a; s <= b; ++s)
|
|
|
|
|
size += insn->getSrc(s)->reg.size;
|
|
|
|
|
if (!size)
|
|
|
|
|
return;
|
|
|
|
|
LValue *lval = new_LValue(func, FILE_GPR);
|
|
|
|
|
lval->reg.size = size;
|
|
|
|
|
|
|
|
|
|
Value *save[3];
|
|
|
|
|
insn->takeExtraSources(0, save);
|
|
|
|
|
|
|
|
|
|
Instruction *merge = new_Instruction(func, OP_MERGE, typeOfSize(size));
|
|
|
|
|
merge->setDef(0, lval);
|
|
|
|
|
for (int s = a, i = 0; s <= b; ++s, ++i) {
|
|
|
|
|
merge->setSrc(i, insn->getSrc(s));
|
|
|
|
|
}
|
2016-01-30 22:08:06 -05:00
|
|
|
insn->moveSources(b + 1, a - b);
|
2012-04-09 20:58:39 +02:00
|
|
|
insn->setSrc(a, lval);
|
|
|
|
|
insn->bb->insertBefore(insn, merge);
|
|
|
|
|
|
|
|
|
|
insn->putExtraSources(0, save);
|
|
|
|
|
|
|
|
|
|
constrList.push_back(merge);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-05 18:34:22 +02:00
|
|
|
bool
|
|
|
|
|
RegAlloc::InsertConstraintsPass::isScalarTexGM107(TexInstruction *tex)
|
|
|
|
|
{
|
|
|
|
|
if (tex->tex.sIndirectSrc >= 0 ||
|
2019-01-18 02:43:54 +01:00
|
|
|
tex->tex.rIndirectSrc >= 0 ||
|
|
|
|
|
tex->tex.derivAll)
|
2018-08-05 18:34:22 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (tex->tex.mask == 5 || tex->tex.mask == 6)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
switch (tex->op) {
|
|
|
|
|
case OP_TEX:
|
|
|
|
|
case OP_TXF:
|
|
|
|
|
case OP_TXG:
|
|
|
|
|
case OP_TXL:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// legal variants:
|
|
|
|
|
// TEXS.1D.LZ
|
|
|
|
|
// TEXS.2D
|
|
|
|
|
// TEXS.2D.LZ
|
|
|
|
|
// TEXS.2D.LL
|
|
|
|
|
// TEXS.2D.DC
|
|
|
|
|
// TEXS.2D.LL.DC
|
|
|
|
|
// TEXS.2D.LZ.DC
|
|
|
|
|
// TEXS.A2D
|
|
|
|
|
// TEXS.A2D.LZ
|
|
|
|
|
// TEXS.A2D.LZ.DC
|
|
|
|
|
// TEXS.3D
|
|
|
|
|
// TEXS.3D.LZ
|
|
|
|
|
// TEXS.CUBE
|
|
|
|
|
// TEXS.CUBE.LL
|
|
|
|
|
|
|
|
|
|
// TLDS.1D.LZ
|
|
|
|
|
// TLDS.1D.LL
|
|
|
|
|
// TLDS.2D.LZ
|
|
|
|
|
// TLSD.2D.LZ.AOFFI
|
|
|
|
|
// TLDS.2D.LZ.MZ
|
|
|
|
|
// TLDS.2D.LL
|
|
|
|
|
// TLDS.2D.LL.AOFFI
|
|
|
|
|
// TLDS.A2D.LZ
|
|
|
|
|
// TLDS.3D.LZ
|
|
|
|
|
|
|
|
|
|
// TLD4S: all 2D/RECT variants and only offset
|
|
|
|
|
|
|
|
|
|
switch (tex->op) {
|
|
|
|
|
case OP_TEX:
|
|
|
|
|
if (tex->tex.useOffsets)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
switch (tex->tex.target.getEnum()) {
|
|
|
|
|
case TEX_TARGET_1D:
|
|
|
|
|
case TEX_TARGET_2D_ARRAY_SHADOW:
|
|
|
|
|
return tex->tex.levelZero;
|
|
|
|
|
case TEX_TARGET_CUBE:
|
|
|
|
|
return !tex->tex.levelZero;
|
|
|
|
|
case TEX_TARGET_2D:
|
|
|
|
|
case TEX_TARGET_2D_ARRAY:
|
|
|
|
|
case TEX_TARGET_2D_SHADOW:
|
|
|
|
|
case TEX_TARGET_3D:
|
|
|
|
|
case TEX_TARGET_RECT:
|
|
|
|
|
case TEX_TARGET_RECT_SHADOW:
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OP_TXL:
|
|
|
|
|
if (tex->tex.useOffsets)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
switch (tex->tex.target.getEnum()) {
|
|
|
|
|
case TEX_TARGET_2D:
|
|
|
|
|
case TEX_TARGET_2D_SHADOW:
|
|
|
|
|
case TEX_TARGET_RECT:
|
|
|
|
|
case TEX_TARGET_RECT_SHADOW:
|
|
|
|
|
case TEX_TARGET_CUBE:
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OP_TXF:
|
|
|
|
|
switch (tex->tex.target.getEnum()) {
|
|
|
|
|
case TEX_TARGET_1D:
|
|
|
|
|
return !tex->tex.useOffsets;
|
|
|
|
|
case TEX_TARGET_2D:
|
|
|
|
|
case TEX_TARGET_RECT:
|
|
|
|
|
return true;
|
|
|
|
|
case TEX_TARGET_2D_ARRAY:
|
|
|
|
|
case TEX_TARGET_2D_MS:
|
|
|
|
|
case TEX_TARGET_3D:
|
|
|
|
|
return !tex->tex.useOffsets && tex->tex.levelZero;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OP_TXG:
|
|
|
|
|
if (tex->tex.useOffsets > 1)
|
|
|
|
|
return false;
|
|
|
|
|
if (tex->tex.mask != 0x3 && tex->tex.mask != 0xf)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
switch (tex->tex.target.getEnum()) {
|
|
|
|
|
case TEX_TARGET_2D:
|
|
|
|
|
case TEX_TARGET_2D_MS:
|
|
|
|
|
case TEX_TARGET_2D_SHADOW:
|
|
|
|
|
case TEX_TARGET_RECT:
|
|
|
|
|
case TEX_TARGET_RECT_SHADOW:
|
|
|
|
|
return true;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::handleScalarTexGM107(TexInstruction *tex)
|
|
|
|
|
{
|
|
|
|
|
int defCount = tex->defCount(0xff);
|
|
|
|
|
int srcCount = tex->srcCount(0xff);
|
|
|
|
|
|
|
|
|
|
tex->tex.scalar = true;
|
|
|
|
|
|
|
|
|
|
// 1. handle defs
|
|
|
|
|
if (defCount > 3)
|
|
|
|
|
condenseDefs(tex, 2, 3);
|
|
|
|
|
if (defCount > 1)
|
|
|
|
|
condenseDefs(tex, 0, 1);
|
|
|
|
|
|
|
|
|
|
// 2. handle srcs
|
|
|
|
|
// special case for TXF.A2D
|
|
|
|
|
if (tex->op == OP_TXF && tex->tex.target == TEX_TARGET_2D_ARRAY) {
|
|
|
|
|
assert(srcCount >= 3);
|
|
|
|
|
condenseSrcs(tex, 1, 2);
|
|
|
|
|
} else {
|
|
|
|
|
if (srcCount > 3)
|
|
|
|
|
condenseSrcs(tex, 2, 3);
|
|
|
|
|
// only if we have more than 2 sources
|
|
|
|
|
if (srcCount > 2)
|
|
|
|
|
condenseSrcs(tex, 0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(!tex->defExists(2) && !tex->srcExists(2));
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-09 15:56:05 +10:00
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::texConstraintGM107(TexInstruction *tex)
|
|
|
|
|
{
|
|
|
|
|
int n, s;
|
|
|
|
|
|
|
|
|
|
if (isTextureOp(tex->op))
|
|
|
|
|
textureMask(tex);
|
2018-08-05 18:34:22 +02:00
|
|
|
|
2020-06-07 09:52:35 +10:00
|
|
|
if (targ->getChipset() < NVISA_GV100_CHIPSET) {
|
|
|
|
|
if (isScalarTexGM107(tex)) {
|
|
|
|
|
handleScalarTexGM107(tex);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-08-05 18:34:22 +02:00
|
|
|
|
2020-06-07 09:52:35 +10:00
|
|
|
assert(!tex->tex.scalar);
|
|
|
|
|
condenseDefs(tex);
|
|
|
|
|
} else {
|
|
|
|
|
if (isTextureOp(tex->op)) {
|
|
|
|
|
int defCount = tex->defCount(0xff);
|
|
|
|
|
if (defCount > 3)
|
|
|
|
|
condenseDefs(tex, 2, 3);
|
|
|
|
|
if (defCount > 1)
|
|
|
|
|
condenseDefs(tex, 0, 1);
|
|
|
|
|
} else {
|
|
|
|
|
condenseDefs(tex);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-09 15:56:05 +10:00
|
|
|
|
2016-05-19 11:59:25 +02:00
|
|
|
if (isSurfaceOp(tex->op)) {
|
|
|
|
|
int s = tex->tex.target.getDim() +
|
|
|
|
|
(tex->tex.target.isArray() || tex->tex.target.isCube());
|
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
|
|
switch (tex->op) {
|
|
|
|
|
case OP_SUSTB:
|
|
|
|
|
case OP_SUSTP:
|
|
|
|
|
n = 4;
|
|
|
|
|
break;
|
|
|
|
|
case OP_SUREDB:
|
|
|
|
|
case OP_SUREDP:
|
|
|
|
|
if (tex->subOp == NV50_IR_SUBOP_ATOM_CAS)
|
|
|
|
|
n = 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (s > 1)
|
|
|
|
|
condenseSrcs(tex, 0, s - 1);
|
|
|
|
|
if (n > 1)
|
|
|
|
|
condenseSrcs(tex, 1, n); // do not condense the tex handle
|
2014-05-09 15:56:05 +10:00
|
|
|
} else
|
|
|
|
|
if (isTextureOp(tex->op)) {
|
|
|
|
|
if (tex->op != OP_TXQ) {
|
|
|
|
|
s = tex->tex.target.getArgCount() - tex->tex.target.isMS();
|
2014-09-25 03:51:37 -04:00
|
|
|
if (tex->op == OP_TXD) {
|
|
|
|
|
// Indirect handle belongs in the first arg
|
|
|
|
|
if (tex->tex.rIndirectSrc >= 0)
|
|
|
|
|
s++;
|
|
|
|
|
if (!tex->tex.target.isArray() && tex->tex.useOffsets)
|
|
|
|
|
s++;
|
|
|
|
|
}
|
2019-02-02 02:56:48 -05:00
|
|
|
n = tex->srcCount(0xff, true) - s;
|
|
|
|
|
// TODO: Is this necessary? Perhaps just has to be aligned to the
|
|
|
|
|
// level that the first arg is, not necessarily to 4. This
|
|
|
|
|
// requirement has not been rigorously verified, as it has been on
|
|
|
|
|
// Kepler.
|
|
|
|
|
if (n > 0 && n < 3) {
|
|
|
|
|
if (tex->srcExists(n + s)) // move potential predicate out of the way
|
|
|
|
|
tex->moveSources(n + s, 3 - n);
|
|
|
|
|
while (n < 3)
|
|
|
|
|
tex->setSrc(s + n++, new_LValue(func, FILE_GPR));
|
|
|
|
|
}
|
2014-05-09 15:56:05 +10:00
|
|
|
} else {
|
2019-02-02 02:56:48 -05:00
|
|
|
s = tex->srcCount(0xff, true);
|
2014-05-09 15:56:05 +10:00
|
|
|
n = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (s > 1)
|
|
|
|
|
condenseSrcs(tex, 0, s - 1);
|
|
|
|
|
if (n > 1) // NOTE: first call modified positions already
|
|
|
|
|
condenseSrcs(tex, 1, n);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-09 20:58:39 +02:00
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::texConstraintNVE0(TexInstruction *tex)
|
|
|
|
|
{
|
2013-02-23 00:00:27 +01:00
|
|
|
if (isTextureOp(tex->op))
|
|
|
|
|
textureMask(tex);
|
2012-04-09 20:58:39 +02:00
|
|
|
condenseDefs(tex);
|
|
|
|
|
|
2013-02-23 00:00:27 +01:00
|
|
|
if (tex->op == OP_SUSTB || tex->op == OP_SUSTP) {
|
2016-05-20 00:52:26 +02:00
|
|
|
condenseSrcs(tex, 3, 6);
|
2012-04-09 20:58:39 +02:00
|
|
|
} else
|
2013-02-23 00:00:27 +01:00
|
|
|
if (isTextureOp(tex->op)) {
|
|
|
|
|
int n = tex->srcCount(0xff, true);
|
2019-02-02 02:56:48 -05:00
|
|
|
int s = n > 4 ? 4 : n;
|
|
|
|
|
if (n > 4 && n < 7) {
|
|
|
|
|
if (tex->srcExists(n)) // move potential predicate out of the way
|
|
|
|
|
tex->moveSources(n, 7 - n);
|
|
|
|
|
|
|
|
|
|
while (n < 7)
|
|
|
|
|
tex->setSrc(n++, new_LValue(func, FILE_GPR));
|
2013-02-23 00:00:27 +01:00
|
|
|
}
|
2019-02-02 02:56:48 -05:00
|
|
|
if (s > 1)
|
|
|
|
|
condenseSrcs(tex, 0, s - 1);
|
|
|
|
|
if (n > 4)
|
|
|
|
|
condenseSrcs(tex, 1, n - s);
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::texConstraintNVC0(TexInstruction *tex)
|
|
|
|
|
{
|
|
|
|
|
int n, s;
|
|
|
|
|
|
2015-11-29 15:50:09 +01:00
|
|
|
if (isTextureOp(tex->op))
|
|
|
|
|
textureMask(tex);
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
if (tex->op == OP_TXQ) {
|
|
|
|
|
s = tex->srcCount(0xff);
|
|
|
|
|
n = 0;
|
2016-04-27 18:27:10 +02:00
|
|
|
} else if (isSurfaceOp(tex->op)) {
|
|
|
|
|
s = tex->tex.target.getDim() + (tex->tex.target.isArray() || tex->tex.target.isCube());
|
|
|
|
|
if (tex->op == OP_SUSTB || tex->op == OP_SUSTP)
|
|
|
|
|
n = 4;
|
|
|
|
|
else
|
|
|
|
|
n = 0;
|
2012-04-09 20:58:39 +02:00
|
|
|
} else {
|
2014-03-20 17:37:00 -04:00
|
|
|
s = tex->tex.target.getArgCount() - tex->tex.target.isMS();
|
2012-04-09 20:58:39 +02:00
|
|
|
if (!tex->tex.target.isArray() &&
|
|
|
|
|
(tex->tex.rIndirectSrc >= 0 || tex->tex.sIndirectSrc >= 0))
|
|
|
|
|
++s;
|
|
|
|
|
if (tex->op == OP_TXD && tex->tex.useOffsets)
|
|
|
|
|
++s;
|
|
|
|
|
n = tex->srcCount(0xff) - s;
|
|
|
|
|
assert(n <= 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (s > 1)
|
|
|
|
|
condenseSrcs(tex, 0, s - 1);
|
2012-05-05 13:30:03 +02:00
|
|
|
if (n > 1) // NOTE: first call modified positions already
|
|
|
|
|
condenseSrcs(tex, 1, n);
|
2012-04-09 20:58:39 +02:00
|
|
|
|
|
|
|
|
condenseDefs(tex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::texConstraintNV50(TexInstruction *tex)
|
|
|
|
|
{
|
|
|
|
|
Value *pred = tex->getPredicate();
|
|
|
|
|
if (pred)
|
|
|
|
|
tex->setPredicate(tex->cc, NULL);
|
|
|
|
|
|
|
|
|
|
textureMask(tex);
|
|
|
|
|
|
|
|
|
|
assert(tex->defExists(0) && tex->srcExists(0));
|
|
|
|
|
// make src and def count match
|
|
|
|
|
int c;
|
|
|
|
|
for (c = 0; tex->srcExists(c) || tex->defExists(c); ++c) {
|
|
|
|
|
if (!tex->srcExists(c))
|
|
|
|
|
tex->setSrc(c, new_LValue(func, tex->getSrc(0)->asLValue()));
|
2018-04-09 22:19:35 -04:00
|
|
|
else
|
|
|
|
|
insertConstraintMove(tex, c);
|
2012-04-09 20:58:39 +02:00
|
|
|
if (!tex->defExists(c))
|
|
|
|
|
tex->setDef(c, new_LValue(func, tex->getDef(0)->asLValue()));
|
|
|
|
|
}
|
|
|
|
|
if (pred)
|
|
|
|
|
tex->setPredicate(tex->cc, pred);
|
|
|
|
|
condenseDefs(tex);
|
|
|
|
|
condenseSrcs(tex, 0, c - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
// Insert constraint markers for instructions whose multiple sources must be
|
|
|
|
|
// located in consecutive registers.
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::InsertConstraintsPass::visit(BasicBlock *bb)
|
|
|
|
|
{
|
|
|
|
|
TexInstruction *tex;
|
|
|
|
|
Instruction *next;
|
2012-04-09 20:58:39 +02:00
|
|
|
int s, size;
|
|
|
|
|
|
|
|
|
|
targ = bb->getProgram()->getTarget();
|
2011-09-14 16:18:23 +02:00
|
|
|
|
|
|
|
|
for (Instruction *i = bb->getEntry(); i; i = next) {
|
|
|
|
|
next = i->next;
|
|
|
|
|
|
|
|
|
|
if ((tex = i->asTex())) {
|
2012-04-09 20:58:39 +02:00
|
|
|
switch (targ->getChipset() & ~0xf) {
|
|
|
|
|
case 0x50:
|
|
|
|
|
case 0x80:
|
|
|
|
|
case 0x90:
|
|
|
|
|
case 0xa0:
|
|
|
|
|
texConstraintNV50(tex);
|
|
|
|
|
break;
|
|
|
|
|
case 0xc0:
|
|
|
|
|
case 0xd0:
|
|
|
|
|
texConstraintNVC0(tex);
|
|
|
|
|
break;
|
|
|
|
|
case 0xe0:
|
2013-12-06 09:09:42 +10:00
|
|
|
case 0xf0:
|
|
|
|
|
case 0x100:
|
2012-04-09 20:58:39 +02:00
|
|
|
texConstraintNVE0(tex);
|
|
|
|
|
break;
|
2014-05-09 15:56:05 +10:00
|
|
|
case 0x110:
|
2016-02-16 07:56:44 +10:00
|
|
|
case 0x120:
|
2016-07-09 10:06:44 +10:00
|
|
|
case 0x130:
|
2020-06-07 09:52:35 +10:00
|
|
|
case 0x140:
|
2020-06-07 09:52:37 +10:00
|
|
|
case 0x160:
|
2022-05-30 23:39:59 +02:00
|
|
|
case 0x170:
|
2023-07-18 22:22:43 +02:00
|
|
|
case 0x190:
|
2014-05-09 15:56:05 +10:00
|
|
|
texConstraintGM107(tex);
|
|
|
|
|
break;
|
2012-04-09 20:58:39 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
if (i->op == OP_EXPORT || i->op == OP_STORE) {
|
|
|
|
|
for (size = typeSizeof(i->dType), s = 1; size > 0; ++s) {
|
|
|
|
|
assert(i->srcExists(s));
|
|
|
|
|
size -= i->getSrc(s)->reg.size;
|
|
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
condenseSrcs(i, 1, s - 1);
|
2011-09-14 16:18:23 +02:00
|
|
|
} else
|
2012-04-09 20:58:39 +02:00
|
|
|
if (i->op == OP_LOAD || i->op == OP_VFETCH) {
|
|
|
|
|
condenseDefs(i);
|
2012-04-09 20:40:35 +02:00
|
|
|
if (i->src(0).isIndirect(0) && typeSizeof(i->dType) >= 8)
|
|
|
|
|
addHazard(i, i->src(0).getIndirect(0));
|
2015-07-23 02:27:04 -04:00
|
|
|
if (i->src(0).isIndirect(1) && typeSizeof(i->dType) >= 8)
|
|
|
|
|
addHazard(i, i->src(0).getIndirect(1));
|
2021-03-20 23:40:00 -04:00
|
|
|
if (i->op == OP_LOAD && i->fixed && targ->getChipset() < 0xc0) {
|
|
|
|
|
// Add a hazard to make sure we keep the op around. These are used
|
|
|
|
|
// for membars.
|
|
|
|
|
Instruction *nop = new_Instruction(func, OP_NOP, i->dType);
|
|
|
|
|
nop->setSrc(0, i->getDef(0));
|
|
|
|
|
i->bb->insertAfter(i, nop);
|
|
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
} else
|
2013-02-25 14:45:52 +01:00
|
|
|
if (i->op == OP_UNION ||
|
|
|
|
|
i->op == OP_MERGE ||
|
|
|
|
|
i->op == OP_SPLIT) {
|
2012-04-09 20:58:39 +02:00
|
|
|
constrList.push_back(i);
|
2021-02-27 18:24:44 -05:00
|
|
|
} else
|
|
|
|
|
if (i->op == OP_ATOM && i->subOp == NV50_IR_SUBOP_ATOM_CAS &&
|
|
|
|
|
targ->getChipset() < 0xc0) {
|
|
|
|
|
// Like a hazard, but for a def.
|
|
|
|
|
Instruction *nop = new_Instruction(func, OP_NOP, i->dType);
|
|
|
|
|
nop->setSrc(0, i->getDef(0));
|
|
|
|
|
i->bb->insertAfter(i, nop);
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-09 22:19:35 -04:00
|
|
|
void
|
|
|
|
|
RegAlloc::InsertConstraintsPass::insertConstraintMove(Instruction *cst, int s)
|
|
|
|
|
{
|
|
|
|
|
const uint8_t size = cst->src(s).getSize();
|
|
|
|
|
|
|
|
|
|
assert(cst->getSrc(s)->defs.size() == 1); // still SSA
|
|
|
|
|
|
|
|
|
|
Instruction *defi = cst->getSrc(s)->defs.front()->getInsn();
|
2019-02-02 02:56:48 -05:00
|
|
|
|
2018-04-09 22:19:35 -04:00
|
|
|
bool imm = defi->op == OP_MOV &&
|
|
|
|
|
defi->src(0).getFile() == FILE_IMMEDIATE;
|
|
|
|
|
bool load = defi->op == OP_LOAD &&
|
|
|
|
|
defi->src(0).getFile() == FILE_MEMORY_CONST &&
|
|
|
|
|
!defi->src(0).isIndirect(0);
|
|
|
|
|
// catch some cases where don't really need MOVs
|
nv50/ir/ra: Fix copying compound for moves
In order to reduce moves when coalescing multiple registers into a
larger register, RA will try to coalesce MERGE instructions with their
definitions. For example, for something like this in GLSL:
uint a = ...;
uint b = ...;
uint64 x = packUint2x32(a, b);
The compiler will try to coalesce x with a and b, in the same way as
something like:
uint a = ...;
uint b = ...;
...
uint x = phi(a, b);
with the crucial difference that the definitions of a and b only clobber
part of the register, instead of the whole thing. This information is
carried through the compound flag and compMask bitmask. If compound is
set, then the value has been coalesced in such a way that not all the
defs clobber the entire register. The compMask bitmask describes which
subregister each def clobbers, although it does it in a slightly
convoluted way. It's an invariant that once compound is set on one def,
it must be set for all the defs in a given coalesced value.
In more detail, the constraints pass will first create extra moves:
uint a = ...;
uint b = ...;
uint a' = a;
uint b' = b;
uint64 x = packUint2x32(a', b');
and then RA will merge values involved in MERGE/SPLIT instructions,
merging x with a' and b' and making the combined value compound -- this
is relatively simple, and will always succeed since we just created a'
and b', so they never interfere with x, and x has no other definitions,
since we haven't started coalescing moves yet. Basically, we just replaced
the MERGE instruction with an equivalent sequence of partial writes to the
destination. The tricky part comes when we try to merge a' with a
and b' with b. We need to transfer the compound information from a' to a
and b' to b, which copyCompound() does, but we also need to transfer it
to any defs coalesced with a and b, which the code failed to do. Similarly,
if x is the argument to a phi instruction, then when we try to merge it
with other arguments to the same phi by coalescing moves, we'd have
problems guaranteeing that all the other merged defs stay up-to-date.
One tricky part of fixing this is that in order to properly propagate
the information from a' to a, we need to do it before the defs for a and
a' are merged in coalesceValues(), since we need to know which defs are
merged with a but not a' -- after coalesceValues() returns, all the defs
have been combined, so we don't know which is which. I took the approach
of calling copyCompound() inside coalesceValues(), instead of
afterwards.
v2: (mhenning) This now loops over mergedDefs in copyCompound, to update
it for changes made in bcf6a9ec
Cc: Ilia Mirkin <imirkin@alum.mit.edu>
Cc: Karol Herbst <kherbst@redhat.com>
Tested-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: M Henning <drawoc@darkrefraction.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17115>
2018-01-08 19:25:01 -05:00
|
|
|
if (cst->getSrc(s)->refCount() == 1 && !defi->constrainedDefs()
|
|
|
|
|
&& defi->op != OP_MERGE && defi->op != OP_SPLIT) {
|
2018-04-09 22:19:35 -04:00
|
|
|
if (imm || load) {
|
|
|
|
|
// Move the defi right before the cst. No point in expanding
|
|
|
|
|
// the range.
|
|
|
|
|
defi->bb->remove(defi);
|
|
|
|
|
cst->bb->insertBefore(cst, defi);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LValue *lval = new_LValue(func, cst->src(s).getFile());
|
|
|
|
|
lval->reg.size = size;
|
|
|
|
|
|
|
|
|
|
Instruction *mov = new_Instruction(func, OP_MOV, typeOfSize(size));
|
|
|
|
|
mov->setDef(0, lval);
|
|
|
|
|
mov->setSrc(0, cst->getSrc(s));
|
|
|
|
|
|
|
|
|
|
if (load) {
|
|
|
|
|
mov->op = OP_LOAD;
|
|
|
|
|
mov->setSrc(0, defi->getSrc(0));
|
|
|
|
|
} else if (imm) {
|
|
|
|
|
mov->setSrc(0, defi->getSrc(0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (defi->getPredicate())
|
|
|
|
|
mov->setPredicate(defi->cc, defi->getPredicate());
|
|
|
|
|
|
|
|
|
|
cst->setSrc(s, mov->getDef(0));
|
|
|
|
|
cst->bb->insertBefore(cst, mov);
|
2018-05-02 18:36:41 +02:00
|
|
|
|
|
|
|
|
cst->getDef(0)->asLValue()->noSpill = 1; // doesn't help
|
2018-04-09 22:19:35 -04:00
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
// Insert extra moves so that, if multiple register constraints on a value are
|
|
|
|
|
// in conflict, these conflicts can be resolved.
|
|
|
|
|
bool
|
|
|
|
|
RegAlloc::InsertConstraintsPass::insertConstraintMoves()
|
|
|
|
|
{
|
2012-04-09 20:58:39 +02:00
|
|
|
for (std::list<Instruction *>::iterator it = constrList.begin();
|
|
|
|
|
it != constrList.end();
|
|
|
|
|
++it) {
|
|
|
|
|
Instruction *cst = *it;
|
|
|
|
|
Instruction *mov;
|
|
|
|
|
|
2021-09-01 16:39:49 +02:00
|
|
|
if (cst->op == OP_SPLIT && false) {
|
2012-04-09 20:58:39 +02:00
|
|
|
// spilling splits is annoying, just make sure they're separate
|
|
|
|
|
for (int d = 0; cst->defExists(d); ++d) {
|
|
|
|
|
if (!cst->getDef(d)->refCount())
|
|
|
|
|
continue;
|
|
|
|
|
LValue *lval = new_LValue(func, cst->def(d).getFile());
|
|
|
|
|
const uint8_t size = cst->def(d).getSize();
|
|
|
|
|
lval->reg.size = size;
|
|
|
|
|
|
|
|
|
|
mov = new_Instruction(func, OP_MOV, typeOfSize(size));
|
|
|
|
|
mov->setSrc(0, lval);
|
|
|
|
|
mov->setDef(0, cst->getDef(d));
|
|
|
|
|
cst->setDef(d, mov->getSrc(0));
|
|
|
|
|
cst->bb->insertAfter(cst, mov);
|
|
|
|
|
|
|
|
|
|
cst->getSrc(0)->asLValue()->noSpill = 1;
|
|
|
|
|
mov->getSrc(0)->asLValue()->noSpill = 1;
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
if (cst->op == OP_MERGE || cst->op == OP_UNION) {
|
|
|
|
|
for (int s = 0; cst->srcExists(s); ++s) {
|
|
|
|
|
const uint8_t size = cst->src(s).getSize();
|
|
|
|
|
|
|
|
|
|
if (!cst->getSrc(s)->defs.size()) {
|
|
|
|
|
mov = new_Instruction(func, OP_NOP, typeOfSize(size));
|
|
|
|
|
mov->setDef(0, cst->getSrc(s));
|
|
|
|
|
cst->bb->insertBefore(cst, mov);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-09 22:19:35 -04:00
|
|
|
insertConstraintMove(cst, s);
|
2012-04-09 20:58:39 +02:00
|
|
|
}
|
2011-09-14 16:18:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
2012-04-09 20:58:39 +02:00
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-19 12:22:07 -04:00
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
|
|
bool Program::registerAllocation()
|
|
|
|
|
{
|
|
|
|
|
RegAlloc ra(this);
|
|
|
|
|
return ra.exec();
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-14 16:18:23 +02:00
|
|
|
} // namespace nv50_ir
|