Repository: ispc/ispc

Issue #2322: Investigate outputting the PDB debugging format for Windows targets.
Created: 2022-05-11T04:37:49Z
LLVM added support for the PDB format back in 2017, and it has improved much since then.  Other front end teams (such as Unity Burst Compiler) have been using it to great success for a number of years.  I think this could improve the debugging experience with Visual Studio and vscode with MSVC tools.
http://blog.llvm.org/2017/08/llvm-on-windows-now-supports-pdb-debug.html

Duplicate issue #2345: Corrupt callstack while inside ISPC functions
Created: 2022-07-15T08:11:12Z
I'm doing some optimisations by replacing C++ with ISPC, and am finding it very difficult to use sampling profilers like Visual Studio's built-in CPU profiler, or third-party products such as Superluminal.
The timings surface in the wrong place in the call tree, and I believe it's because the callstack is corrupt while inside the ISPC function, resulting in samples being stored with a bad hierarchy behind them.
I'm using MSVC 16.11, ISPC 1.18.0.
You can see this when stepping through a simple contrived function such as:
// Bug.ispc
export uniform float BugFunction(uniform float x, uniform float y)
{
	uniform float xCos = cos(x);
	uniform float yCos = cos(y);
	return xCos + yCos;
}

// main.cpp
#include "bug.ispc.generated.h"

int main(int argc, char** argv)
{
	float result = ispc::BugFunction(1.0f, 2.0f);
	return (int)result;
}

In this gif, I am simply stepping through the program with F11. You can see that the callstack view on the right loses most entries once inside BugFunction.

I've not yet found any combination of ISPC parameters that fixes this. The gif above was produced using:
"C:\Program Files\ISPC\ispc-v1.18.0-windows\bin\ispc.exe" %(FullPath) -o $(IntermediateOutputPath)%(Identity).obj -h $(ProjectDir)%(Identity).generated.h -g -O1 --target=avx2-i32x8 --no-omit-frame-pointer
In the disassembly view, you can see a bit more of what's going on - the callstack corrupts on the very first instruction - sub rsp 88h, and is restored on the final add rsp 88h before the ret.

A more elaborate contrived function to show up the problem in the VS profiler (as the previous example is too quick for a sampling profiler):
// Bug.ispc

export uniform float BugFunction(uniform float x, uniform float y)
{
	uniform float total = 0;
	for (int64 i = 0; i < 10000000; ++i)
		total += cos(x);
	return total;
}

// main.cpp
#include <cmath>
#include <ctime>
#include <cstdint>
#include "bug.ispc.generated.h"

// C++ version of ispc::BugFunction
float BugFunction(float x, float y)
{
	float total = 0;
	for (int64_t i = 0; i < 1000000; ++i)
		total += cos(x);
	return total;
}

float DoBugFunction()
{
	float total = (float)rand();
	for (int i = 0; i < 1000; ++i)
		total = cos(total);
	return ispc::BugFunction(1.0f, total); // Swap for just BugFunction(1.0f, total) to see the "working" profile
}

int main(int argc, char** argv)
{
	std::srand((unsigned int)std::time(nullptr));
	float result = 0;
	for (int i = 0; i < 1000; ++i)
		result += DoBugFunction();
	return (int)result;
}

Note that ispc::BugFunction shows up under a "[Unwalkable]" heading in the wrong place in the call tree

This is how I would expect it to look (as if it were written in pure C++):

Closing comment (2022-07-15T23:58:59Z): I think this could be related to #2322.