Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lldb/packages/Python/lldbsuite/test/builders/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ def getLibCxxArgs(self):
return libcpp_args
return []

def getHipccArgs(self):
if configuration.hipcc_path:
return ["HIPCC={}".format(configuration.hipcc_path)]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is HPICC valid for all GPUs, or just AMD?

return []

def getLLDBObjRoot(self):
return ["LLDB_OBJ_ROOT={}".format(configuration.lldb_obj_root)]

Expand Down Expand Up @@ -293,6 +298,7 @@ def getBuildCommand(
self.getSDKRootSpec(),
self.getModuleCacheSpec(),
self.getLibCxxArgs(),
self.getHipccArgs(),
self.getLLDBObjRoot(),
self.getCmdLine(dictionary),
]
Expand Down
1 change: 1 addition & 0 deletions lldb/packages/Python/lldbsuite/test/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
dsymutil = None
sdkroot = None
make_path = None
hipcc_path = None
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this AMD specific? If so, please name this better to specify this like amd_gpu_cc_path. If this is a generic compiler for any GPU then gpu_cc_path. Not sure if we ever expect the test suite to run for more than one GPU? If not, then we should do something like gpu_cc_path. Else we might need a dictionary of gpu name or target triple to the compiler path.


# The overriden dwarf verison.
# Don't use this to test the current compiler's
Expand Down
3 changes: 3 additions & 0 deletions lldb/packages/Python/lldbsuite/test/dotest.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ def parseOptionsAndInitTestdirs():
configuration.compiler = candidate
break

if args.hipcc_path:
configuration.hipcc_path = os.path.abspath(args.hipcc_path)

if args.make:
configuration.make_path = args.make

Expand Down
9 changes: 9 additions & 0 deletions lldb/packages/Python/lldbsuite/test/dotest_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ def create_parser():
"""Specify the path to sysroot. This overrides apple_sdk sysroot."""
),
)
group.add_argument(
"--hipcc-path",
metavar="path",
dest="hipcc_path",
default="",
help=textwrap.dedent(
"""Specify the path to a ROCM hipcc compiler."""
),
)
Comment on lines +61 to +69
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be more GPU agnostic. We probably don't want to have each GPU maker having to define they own settings like this.

    group.add_argument(
        "--gpu-cc-path",
        metavar="path",
        dest="gpu_cc_path",
        default=None,
        help=textwrap.dedent(
            """Specify the path to a GPU compiler compiler."""
        ),
    )

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we go with agnostic GPU compiler settings, we might need to enable a GPU type. That way if we have many tests that are AMD specific and some that are NVidia specific, we can enable one GPU to be tested and then the GPU tests would only run if they have this GPU type.

group.add_argument(
        "--gpu-type",
        type="string",
        dest="gpu_type",
        default=None,
        help=textwrap.dedent(
            """Specify the the GPU directory to test. Valid values should match a GPU test directory name in llvm-project/lldb/test/gpu folder."""
        ),
    )

That way anyone can add a directory like:

llvm-project/lldb/test/gpu/amd
llvm-project/lldb/test/gpu/nvidia
llvm-project/lldb/test/gpu/mtia

And then we can test one of these directories. If the --gpu-type option is not set, not GPU tests will be run. If it is set, we would check for a directory in llvm-project/lldb/test/gpu and if it matches this setting, we will run the tests for that GPU in addition.

if sys.platform == "darwin":
group.add_argument(
"--apple-sdk",
Expand Down
22 changes: 22 additions & 0 deletions lldb/packages/Python/lldbsuite/test/make/Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,17 @@ else
endif
endif

#----------------------------------------------------------------------
# Override CC and CXX when building a hip application.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have realized that I need to change this file as well for NVIDIA. I tried to pass the path of my compiler to the python test file when running with lldb-dotest but it didn't work. It seems that the path is only correctly passed when running check-lldb.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have agnostic GPU settings and allow users to specify a GPU compiler path, GPU linker path and anything else that is needed to compile.

#
# Use the same hipcc compiler for compiling and linking everything.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace hpicc which gpucc or something that isn't AMD specific?

#----------------------------------------------------------------------
ifneq "$(strip $(HIP_SOURCES))" ""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/HIP_SOURCES/GPU_SOURCES/ ?

override CC := $(HIPCC)
override CXX := $(HIPCC)
Comment on lines +112 to +113
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have a GPUCC defined for the compiler and GPULD for the linker? This way any GPU client can work with this build system?

override CC := $(GPUCC)
override CXX := $(GPULD)

override CC_TYPE := hip
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be CC_TYPE := gpu?

endif

#----------------------------------------------------------------------
# CC defaults to clang.
#
Expand Down Expand Up @@ -303,6 +314,7 @@ endif

CFLAGS += $(CFLAGS_EXTRAS)
CXXFLAGS += -std=c++11 $(CFLAGS) $(ARCH_CXXFLAGS)
HIPFLAGS ?= $(CFLAGS)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a separate HIPFLAGS and should it be named GPU_CFLAGS? If we only allow something to compile as a GPU binary, then we can just use CFLAGS?

# Copy common options to the linker flags (dwarf, arch. & etc).
# Note: we get some 'garbage' options for linker here (such as -I, --isystem & etc).
LDFLAGS += $(CFLAGS)
Expand Down Expand Up @@ -495,6 +507,13 @@ ifneq "$(strip $(OBJCXX_SOURCES))" ""
endif
endif

#----------------------------------------------------------------------
# Check if we have any hip source files
#----------------------------------------------------------------------
ifneq "$(strip $(HIP_SOURCES))" ""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/HIP_SOURCES/GPU_SOURCES/?

OBJECTS +=$(strip $(HIP_SOURCES:.hip=.o))
endif

ifeq ($(CC_TYPE), clang)
CXXFLAGS += --driver-mode=g++
endif
Expand Down Expand Up @@ -632,6 +651,9 @@ endif
%.o: %.mm %.d
$(CXX) $(CXXFLAGS) -MT $@ -MD -MP -MF $*.d -c -o $@ $<

%.o: %.hip %.d
$(HIPCC) $(HIPFLAGS) -MT $@ -MD -MP -MF $*.d -c -o $@ $<
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all of these flags AMD specific? If they are then we need a way to set the default compiler flags for the specific GPU type that we are using, and this would be best done somewhere that checks the GPU type being tested and sets these options as needed for AMD, NVidia, etc

	$(GPUCC) $(GPUFLAGS) -MT $@ -MD -MP -MF $*.d -c -o $@ $<

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the nvcc compiler, which is not clang based, we need a custom version of this line, something like

$(NVCC) $(NVCCFLAGS) -Xcompiler "-MT $@ -MD -MP -MF $*.d" -c -o $@ $<


#----------------------------------------------------------------------
# Automatic variables based on items already entered. Below we create
# an object's lists from the list of sources by replacing all entries
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/gpu/amd/basic/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
HIP_SOURCES := hello_world.hip
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If HIP a valid term for all GPU compilers? Or do we need a separate setting for AMD GPU, NVidia and MTIA?

Rename HIP_SOURCES to GPU_SOURCES?


include Makefile.rules
81 changes: 81 additions & 0 deletions lldb/test/API/gpu/amd/basic/TestBasicAmdGpuPlugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""
Basic tests for the AMDGPU plugin.
"""


import lldb
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *


class BasicAmdGpuTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True

def test_gpu_target_created_on_demand(self):
"""Test that we create the gpu target automatically."""
self.build()

# There should be no targets before we run the program.
self.assertEqual(self.dbg.GetNumTargets(), 0, "There are no targets")

# Set a breakpoint in the CPU source and run to it.
source_spec = lldb.SBFileSpec("hello_world.hip", False)
(cpu_target, cpu_process, cpu_thread, cpu_bkpt) = lldbutil.run_to_source_breakpoint(
self, "// CPU BREAKPOINT - BEFORE LAUNCH", source_spec
)
self.assertEqual(self.dbg.GetTargetAtIndex(0), cpu_target)

# Get the GPU target.
# This target is created at the first CPU stop.
self.assertEqual(self.dbg.GetNumTargets(), 2, "There are two targets")
gpu_target = self.dbg.GetTargetAtIndex(1)
gpu_thread = gpu_target.GetProcess().GetThreadAtIndex(0)
self.assertEqual(gpu_thread.GetName(), "AMD Native Shadow Thread", "GPU thread has the right name")

def test_gpu_breakpoint_hit(self):
"""Test that we create the gpu target automatically."""
self.build()

# Set a breakpoint in the CPU source and run to it.
source = "hello_world.hip"
source_spec = lldb.SBFileSpec(source, False)
(cpu_target, cpu_process, cpu_thread, cpu_bkpt) = lldbutil.run_to_source_breakpoint(
self, "// CPU BREAKPOINT - BEFORE LAUNCH", source_spec
)

# Switch to the GPU target so we can set a breakpoint.
gpu_target = self.dbg.GetTargetAtIndex(1)
gpu_process = gpu_target.GetProcess()
self.dbg.SetSelectedTarget(gpu_target)


# Set a breakpoint in the GPU source.
# This will not yet resolve to a location.
line = line_number(source, "// GPU BREAKPOINT")
gpu_bkpt = lldbutil.run_break_set_by_file_and_line(
self, source, line, num_expected_locations=0, loc_exact=False
)

# Need to run these commands asynchronously to be able to switch targets.
self.setAsync(True)
listener = self.dbg.GetListener()

# Continue the GPU process.
self.runCmd("c")
lldbutil.expect_state_changes(self, listener, gpu_process, [lldb.eStateRunning])

# Continue the CPU process.
self.dbg.SetSelectedTarget(cpu_target)
self.runCmd("c")
lldbutil.expect_state_changes(self, listener, cpu_process, [lldb.eStateRunning])

# TODO: Looks like the CPU is hitting an extra SIGSTOP for some reason so continue again after it stops.
lldbutil.expect_state_changes(self, listener, cpu_process, [lldb.eStateStopped])
self.dbg.SetSelectedTarget(cpu_target)
self.runCmd("c")
lldbutil.expect_state_changes(self, listener, cpu_process, [lldb.eStateRunning])

# GPU breakpoint should get hit.
lldbutil.expect_state_changes(self, listener, gpu_process, [lldb.eStateStopped])
threads = lldbutil.get_threads_stopped_at_breakpoint_id(gpu_process, gpu_bkpt)
self.assertNotEqual(None, threads, "GPU thread should be stopped at breakpoint")
110 changes: 110 additions & 0 deletions lldb/test/API/gpu/amd/basic/hello_world.hip
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// MIT License
//
// Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved.
//
// 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 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.

#include <hip/hip_runtime.h>

#include <iostream>

/// \brief Checks if the provided error code is \p hipSuccess and if not,
/// prints an error message to the standard error output and terminates the
/// program with an error code.
constexpr int error_exit_code = -1;
#define HIP_CHECK(condition) \
{ \
const hipError_t error = condition; \
if (error != hipSuccess) { \
std::cerr << "An error encountered: \"" << hipGetErrorString(error) \
<< "\" at " << __FILE__ << ':' << __LINE__ << std::endl; \
std::exit(error_exit_code); \
} \
}

// Functions marked with __device__ are executed on the device and called from
// the device only.
__device__ unsigned int get_thread_idx() {
// Built-in threadIdx returns the 3D coordinate of the active work item in the
// block of threads.
return threadIdx.x;
}

// Functions marked with __global__ are executed on the device and called from
// the host only.
__global__ void helloworld_kernel(char *str, size_t size) {
unsigned int thread_idx = get_thread_idx();
unsigned int block_idx = blockIdx.x;
unsigned int idx = thread_idx + block_idx * blockDim.x;

char c = 'x';
switch (idx) {
case 0: c = 'H'; break;
case 1: c = 'e'; break;
case 2: c = 'l'; break;
case 3: c = 'l'; break;
case 4: c = 'o'; break;
case 5: c = ','; break;
case 6: c = ' '; break;
case 7: c = 'w'; break;
case 8: c = 'o'; break;
case 9: c = 'r'; break;
case 10: c = 'l'; break;
case 11: c = 'd'; break;
case 12: c = '!'; break;
}

if (idx < size) { // GPU BREAKPOINT
str[idx] = c;
}
}

int main() {
// Allocate host vectors
const size_t size = strlen("Hello, world!");
std::string h_str(size, '?');
printf("%s\n", h_str.c_str()); // CPU BREAKPOINT - BEFORE LAUNCH

// Allocate device memory for the output data
char *d_str;
HIP_CHECK(hipMalloc(&d_str, size));

// Copy data from host to device
printf("Copying data to device...\n");
HIP_CHECK(hipMemcpy(d_str, h_str.data(), size, hipMemcpyHostToDevice));

// Launch the kernel.
printf("Launching kernel...\n");
helloworld_kernel<<<
dim3(1), // 3D grid specifying number of blocks to launch: (1, 1, 1)
dim3(h_str.size()), // 3D grid specifying number of threads to launch: (strlen, 1, 1)
0, // number of bytes of additional shared memory to allocate
hipStreamDefault // stream where the kernel should execute: default stream
>>>(d_str, size);

// Copy data from device to host
printf("Copying data to host...\n"); // CPU BREAKPOINT - AFTER LAUNCH
HIP_CHECK(hipMemcpy(h_str.data(), d_str, h_str.size(), hipMemcpyDeviceToHost));

// Free device memory
HIP_CHECK(hipFree(d_str)); // CPU BREAKPOINT - AFTER FINISH

// Print the output
printf("%s\n", h_str.c_str());
}
2 changes: 2 additions & 0 deletions lldb/test/API/gpu/amd/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
if not "lldb-amdgpu" in config.enabled_plugins:
config.unsupported = True
3 changes: 3 additions & 0 deletions lldb/test/API/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ def delete_module_cache(path):
if is_configured("test_compiler"):
dotest_cmd += ["--compiler", config.test_compiler]

if is_configured("hipcc_path"):
dotest_cmd += ["--hipcc-path", config.hipcc_path]

if is_configured("dsymutil"):
dotest_cmd += ["--dsymutil", config.dsymutil]

Expand Down
6 changes: 6 additions & 0 deletions lldb/test/API/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ lldb_build_intel_pt = '@LLDB_BUILD_INTEL_PT@'
if lldb_build_intel_pt == '1':
config.enabled_plugins.append('intel-pt')

# GPU Plugins
lldb_enable_amdgpu_plugin = '@LLDB_ENABLE_AMDGPU_PLUGIN@'
if lldb_enable_amdgpu_plugin == 'ON' or lldb_enable_amdgpu_plugin == '1':
config.enabled_plugins.append('lldb-amdgpu')
config.hipcc_path = os.path.join('@ROCM_PATH@', 'bin', 'hipcc')

# Additional dotest arguments can be passed to lit by providing a
# semicolon-separates list: --param dotest-args="arg;arg".
dotest_lit_args_str = lit_config.params.get('dotest-args', None)
Expand Down