// CS 87 - Final Project
// Maria-Elena Solano
//
// This utility simply counts how many CPU cores are in this node
//

#include <stdio.h>                     // C's standard I/O library
#include <stdlib.h>                    // C's standard library
#include <stdint.h>                    // C's exact width int types
#include <unistd.h>                    // C's POSIX API
#include <cuda_runtime.h>              // CUDA runtime library


// macro/constant definitions
#define cuda_try(X)                    ((X) != cudaSuccess)
#define perror_out(X)                  perror(X), fflush(stderr)
#define stderr_out(...)                fprintf(stderr, __VA_ARGS__), \
                                        fflush(stderr)
#define print_out(...)                 printf(__VA_ARGS__), fflush(stdout)


// simple helper container (used in how_many_warp_schedulers_per_SM)
typedef struct sm_to_ws{
  int sm;
  int ws;
} sm_to_ws_t;


void print_count();
void print_count_verbose();
int  how_many_warp_schedulers_per_SM(int arch_major_ver, int arch_minor_ver);


int main(int argc, char** argv){
  int ret;                                  // return value from getopt, and

  // Greedily read all the command line options provided.
  while((ret = getopt(argc, argv, "v")) != -1){
    switch(ret){
      // If option -v, display the full calculation instead
      case 'v':{
        goto verbose;
      }
    }
  }

  // Print the number of cores
  print_count();

  // And return
  goto done;


verbose:
  // If 'verbose' mode, display the model, and the full calculation
  print_count_verbose();  

done:
  exit(EXIT_SUCCESS);
}


// This function prints out the number of independent blocks in the GPU.
//
void print_count(){
  cudaError_t ret;                     // return value of CUDA calls
  int dev, devs;                       // number of devices
  cudaDeviceProp pr;                   // device properties
  uint32_t p;                          // number of concurrent blocks

  // Count how many devices are there. If err or no devices, set p=0 and print.
  if(cuda_try(ret = cudaGetDeviceCount(&devs)) || devs == 0){
    stderr_out("cudaGetDeviceCount error: %s\n", cudaGetErrorString(ret));
    p = 0;
    goto print;
  }

  // Get the device properties of the last device
  dev = devs - 1;
  cudaSetDevice(dev);
  cudaGetDeviceProperties(&pr, dev);

  // Compute the number of concurrent blocks according to the formula 
  //
  //   # of SMs x # of warp schedulers per SM
  //
  p=pr.multiProcessorCount*how_many_warp_schedulers_per_SM(pr.major,pr.minor);

print:
  print_out("%u\n", p);

  return;
}


// This function prints out the number of independent blocks in the GPU,
// showing how the calculation was made: that is, # of SMs x # of warp sche-
// dulers per SM available in the given model.
//
void print_count_verbose(){
  cudaError_t ret;                     // return value of CUDA calls
  int dev, devs;                       // number of devices
  cudaDeviceProp pr;                   // device properties

  // Count how many devices are there. If err, return.
  if(cuda_try(ret = cudaGetDeviceCount(&devs))){
    stderr_out("cudaGetDeviceCount error: %s\n", cudaGetErrorString(ret));
    return;
  }

  // If no devices, notify the user and return
  if(devs == 0){
    print_out("  (No CUDA-enabled GPUs in this machine.)\n");
    return;
  }

  // Get the device properties of the last device
  dev = devs - 1;
  cudaSetDevice(dev);
  cudaGetDeviceProperties(&pr, dev);

  // Show the calculation
  //
  //   # of SMs x # of warp schedulers per SM
  //
  print_out("  (%u SMs x %u warp schedulers per SM)\n",
    pr.multiProcessorCount,
    how_many_warp_schedulers_per_SM(pr.major, pr.minor));

  return;
}

// This function determines how many warp schedulers per SM are there in the
// GPU given ts major and minor architectural version.
// 
// Adapted from helper_cuda.h in the CUDA SDK:
//   (/usr/local/cuda/samples/common/inc/helper_cuda.h).
//
//   major, minor:                     major and minor architecture version
//
//   returns:                          number of warp schedulers per SM
//
int how_many_warp_schedulers_per_SM(int major, int minor){
  int i;
  sm_to_ws_t t[13];                   // Lookup table

  // Tesla architecture (1 warp scheduler per SM)
  t[0] .sm = 0x10;  t[0] .ws = 1;     // Tesla   (SM 1.0) G80 class
  t[1] .sm = 0x11;  t[1] .ws = 1;     // Tesla   (SM 1.1) G8X class
  t[2] .sm = 0x12;  t[2] .ws = 1;     // Tesla   (SM 1.2) G9X class
  t[3] .sm = 0x13;  t[3] .ws = 1;     // Tesla   (SM 1.3) GT200 class

  // Fermi architecture (2 warp schedulers per SM)
  t[4] .sm = 0x20;  t[4] .ws = 2;     // Fermi   (SM 2.0) GF100 class
  t[5] .sm = 0x21;  t[5] .ws = 2;     // Fermi   (SM 2.1) GF10x class

  // Kepler architecture (4 warp schedulers per SM)
  t[6] .sm = 0x30;  t[6] .ws = 4;     // Kepler  (SM 3.0) GK10x class
  t[7] .sm = 0x32;  t[7] .ws = 4;     // Kepler  (SM 3.2) GK10x class
  t[8] .sm = 0x35;  t[8] .ws = 4;     // Kepler  (SM 3.5) GK11x class
  t[9] .sm = 0x37;  t[9] .ws = 4;     // Kepler  (SM 3.7) GK21x class

  // Maxwell architecture (4 warp schedulers per SM)
  t[10].sm = 0x50;  t[10].ws = 4;     // Maxwell (SM 5.0) GM10x class
  t[11].sm = 0x52;  t[11].ws = 4;     // Maxwell (SM 5.2) GM20x class

  // Unknown architecture
  t[12].sm = -1;    t[12].ws = -1;    // Unknown

  for(i=0; i<13; i++){
    if(t[i].sm == ((major << 4) + minor)){
      return t[i].ws;
    }
  }
  return 0;
}

	.file	"tmpxft_0036e9bf_00000000-6_how-many-concurrent-blocks.cudafe1.cpp"
	.text
#APP

#NO_APP
	.type	_ZL26__cudaUnregisterBinaryUtilv, @function
_ZL26__cudaUnregisterBinaryUtilv:
.LFB2046:
	.cfi_startproc
	endbr64
	movq	_ZL20__cudaFatCubinHandle(%rip), %rdi
	jmp	__cudaUnregisterFatBinary@PLT
	.cfi_endproc
.LFE2046:
	.size	_ZL26__cudaUnregisterBinaryUtilv, .-_ZL26__cudaUnregisterBinaryUtilv
	.globl	_Z31how_many_warp_schedulers_per_SMii
	.type	_Z31how_many_warp_schedulers_per_SMii, @function
_Z31how_many_warp_schedulers_per_SMii:
.LFB2043:
	.cfi_startproc
	endbr64
	subq	$120, %rsp
	.cfi_def_cfa_offset 128
	sall	$4, %edi
	movq	%fs:40, %rax
	movq	%rax, 104(%rsp)
	movabsq	$4294967312, %rax
	addl	%esi, %edi
	movq	%rsp, %rdx
	movq	$-1, 96(%rsp)
	movq	%rax, (%rsp)
	incq	%rax
	movq	%rax, 8(%rsp)
	incq	%rax
	movq	%rax, 16(%rsp)
	incq	%rax
	movq	%rax, 24(%rsp)
	movl	$268435457, %eax
	salq	$5, %rax
	movq	%rax, 32(%rsp)
	incq	%rax
	movq	%rax, 40(%rsp)
	movl	$1073741827, %eax
	salq	$4, %rax
	movq	%rax, 48(%rsp)
	addq	$2, %rax
	movq	%rax, 56(%rsp)
	addq	$3, %rax
	movq	%rax, 64(%rsp)
	addq	$2, %rax
	movq	%rax, 72(%rsp)
	addq	$25, %rax
	movq	%rax, 80(%rsp)
	addq	$2, %rax
	movq	%rax, 88(%rsp)
	xorl	%eax, %eax
.L5:
	cmpl	%edi, (%rdx,%rax,8)
	jne	.L3
	cltq
	movl	4(%rsp,%rax,8), %eax
	jmp	.L2
.L3:
	incq	%rax
	cmpq	$13, %rax
	jne	.L5
	xorl	%eax, %eax
.L2:
	movq	104(%rsp), %rdx
	subq	%fs:40, %rdx
	je	.L6
	call	__stack_chk_fail@PLT
.L6:
	addq	$120, %rsp
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2043:
	.size	_Z31how_many_warp_schedulers_per_SMii, .-_Z31how_many_warp_schedulers_per_SMii
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"cudaGetDeviceCount error: %s\n"
.LC1:
	.string	"%u\n"
	.text
	.globl	_Z11print_countv
	.type	_Z11print_countv, @function
_Z11print_countv:
.LFB2041:
	.cfi_startproc
	endbr64
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	subq	$1056, %rsp
	.cfi_def_cfa_offset 1072
	movq	%fs:40, %rax
	movq	%rax, 1048(%rsp)
	xorl	%eax, %eax
	leaq	12(%rsp), %rdi
	call	cudaGetDeviceCount@PLT
	movl	%eax, %edi
	testl	%eax, %eax
	jne	.L11
	movl	12(%rsp), %ebx
	testl	%ebx, %ebx
	je	.L11
	decl	%ebx
	movl	%ebx, %edi
	call	cudaSetDevice@PLT
	leaq	16(%rsp), %rdi
	movl	%ebx, %esi
	call	cudaGetDeviceProperties_v2@PLT
	movl	380(%rsp), %esi
	movl	376(%rsp), %edi
	call	_Z31how_many_warp_schedulers_per_SMii
	imull	404(%rsp), %eax
	movl	%eax, %edx
	jmp	.L12
.L11:
	call	cudaGetErrorString@PLT
	movq	stderr(%rip), %rdi
	movl	$2, %esi
	leaq	.LC0(%rip), %rdx
	movq	%rax, %rcx
	xorl	%eax, %eax
	call	__fprintf_chk@PLT
	movq	stderr(%rip), %rdi
	call	fflush@PLT
	xorl	%edx, %edx
.L12:
	movl	$2, %edi
	xorl	%eax, %eax
	leaq	.LC1(%rip), %rsi
	call	__printf_chk@PLT
	movq	stdout(%rip), %rdi
	call	fflush@PLT
	movq	1048(%rsp), %rax
	subq	%fs:40, %rax
	je	.L13
	call	__stack_chk_fail@PLT
.L13:
	addq	$1056, %rsp
	.cfi_def_cfa_offset 16
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2041:
	.size	_Z11print_countv, .-_Z11print_countv
	.section	.rodata.str1.1
.LC2:
	.string	"  (No CUDA-enabled GPUs in this machine.)\n"
.LC3:
	.string	"  (%u SMs x %u warp schedulers per SM)\n"
	.text
	.globl	_Z19print_count_verbosev
	.type	_Z19print_count_verbosev, @function
_Z19print_count_verbosev:
.LFB2042:
	.cfi_startproc
	endbr64
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	subq	$1056, %rsp
	.cfi_def_cfa_offset 1072
	movq	%fs:40, %rax
	movq	%rax, 1048(%rsp)
	xorl	%eax, %eax
	leaq	12(%rsp), %rdi
	call	cudaGetDeviceCount@PLT
	testl	%eax, %eax
	je	.L19
	movl	%eax, %edi
	call	cudaGetErrorString@PLT
	movq	stderr(%rip), %rdi
	movl	$2, %esi
	leaq	.LC0(%rip), %rdx
	movq	%rax, %rcx
	xorl	%eax, %eax
	call	__fprintf_chk@PLT
	movq	stderr(%rip), %rdi
	jmp	.L25
.L19:
	movl	12(%rsp), %ebx
	testl	%ebx, %ebx
	jne	.L21
	leaq	.LC2(%rip), %rsi
	movl	$2, %edi
	xorl	%eax, %eax
	call	__printf_chk@PLT
	jmp	.L26
.L21:
	decl	%ebx
	movl	%ebx, %edi
	call	cudaSetDevice@PLT
	leaq	16(%rsp), %rdi
	movl	%ebx, %esi
	call	cudaGetDeviceProperties_v2@PLT
	movl	380(%rsp), %esi
	movl	376(%rsp), %edi
	call	_Z31how_many_warp_schedulers_per_SMii
	movl	404(%rsp), %edx
	movl	$2, %edi
	leaq	.LC3(%rip), %rsi
	movl	%eax, %ecx
	xorl	%eax, %eax
	call	__printf_chk@PLT
.L26:
	movq	stdout(%rip), %rdi
.L25:
	call	fflush@PLT
	movq	1048(%rsp), %rax
	subq	%fs:40, %rax
	je	.L23
	call	__stack_chk_fail@PLT
.L23:
	addq	$1056, %rsp
	.cfi_def_cfa_offset 16
	popq	%rbx
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2042:
	.size	_Z19print_count_verbosev, .-_Z19print_count_verbosev
	.section	.rodata.str1.1
.LC4:
	.string	"v"
	.section	.text.startup,"ax",@progbits
	.globl	main
	.type	main, @function
main:
.LFB2040:
	.cfi_startproc
	endbr64
	pushq	%r12
	.cfi_def_cfa_offset 16
	.cfi_offset 12, -16
	leaq	.LC4(%rip), %r12
	pushq	%rbp
	.cfi_def_cfa_offset 24
	.cfi_offset 6, -24
	movq	%rsi, %rbp
	pushq	%rbx
	.cfi_def_cfa_offset 32
	.cfi_offset 3, -32
	movl	%edi, %ebx
.L28:
	movq	%r12, %rdx
	movq	%rbp, %rsi
	movl	%ebx, %edi
	call	getopt@PLT
	cmpl	$-1, %eax
	je	.L33
	cmpl	$118, %eax
	jne	.L28
	call	_Z19print_count_verbosev
	jmp	.L29
.L33:
	call	_Z11print_countv
.L29:
	xorl	%edi, %edi
	call	exit@PLT
	.cfi_endproc
.LFE2040:
	.size	main, .-main
	.type	_ZL24__sti____cudaRegisterAllv, @function
_ZL24__sti____cudaRegisterAllv:
.LFB2069:
	.cfi_startproc
	endbr64
	pushq	%rax
	.cfi_def_cfa_offset 16
	leaq	_ZL15__fatDeviceText(%rip), %rdi
	call	__cudaRegisterFatBinary@PLT
	movq	%rax, %rdi
	movq	%rax, _ZL20__cudaFatCubinHandle(%rip)
	call	__cudaRegisterFatBinaryEnd@PLT
	leaq	_ZL26__cudaUnregisterBinaryUtilv(%rip), %rdi
	popq	%rdx
	.cfi_def_cfa_offset 8
	jmp	atexit@PLT
	.cfi_endproc
.LFE2069:
	.size	_ZL24__sti____cudaRegisterAllv, .-_ZL24__sti____cudaRegisterAllv
	.section	.init_array,"aw"
	.align 8
	.quad	_ZL24__sti____cudaRegisterAllv
	.section	.nvFatBinSegment,"aw"
	.align 8
	.type	_ZL15__fatDeviceText, @object
	.size	_ZL15__fatDeviceText, 24
_ZL15__fatDeviceText:
	.long	1180844977
	.long	1
	.quad	fatbinData
	.quad	0
	.local	_ZL20__cudaFatCubinHandle
	.comm	_ZL20__cudaFatCubinHandle,8,8
	.ident	"GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	1f - 0f
	.long	4f - 1f
	.long	5
0:
	.string	"GNU"
1:
	.align 8
	.long	0xc0000002
	.long	3f - 2f
2:
	.long	0x3
3:
	.align 8
4:

// CS 87 - Final Project
// Maria-Elena Solano
//
// This utility simply counts how many CPU cores are in this node
//

#include <stdio.h>                     // C's standard I/O library
#include <stdlib.h>                    // C's standard library
#include <stdint.h>                    // C's exact width int types
#include <unistd.h>                    // C's POSIX API
#include <hip/hip_runtime.h>              // CUDA runtime library


// macro/constant definitions
#define cuda_try(X)                    ((X) != hipSuccess)
#define perror_out(X)                  perror(X), fflush(stderr)
#define stderr_out(...)                fprintf(stderr, __VA_ARGS__), \
                                        fflush(stderr)
#define print_out(...)                 printf(__VA_ARGS__), fflush(stdout)


// simple helper container (used in how_many_warp_schedulers_per_SM)
typedef struct sm_to_ws{
  int sm;
  int ws;
} sm_to_ws_t;


void print_count();
void print_count_verbose();
int  how_many_warp_schedulers_per_SM(int arch_major_ver, int arch_minor_ver);


int main(int argc, char** argv){
  int ret;                                  // return value from getopt, and

  // Greedily read all the command line options provided.
  while((ret = getopt(argc, argv, "v")) != -1){
    switch(ret){
      // If option -v, display the full calculation instead
      case 'v':{
        goto verbose;
      }
    }
  }

  // Print the number of cores
  print_count();

  // And return
  goto done;


verbose:
  // If 'verbose' mode, display the model, and the full calculation
  print_count_verbose();  

done:
  exit(EXIT_SUCCESS);
}


// This function prints out the number of independent blocks in the GPU.
//
void print_count(){
  hipError_t ret;                     // return value of CUDA calls
  int dev, devs;                       // number of devices
  hipDeviceProp_t pr;                   // device properties
  uint32_t p;                          // number of concurrent blocks

  // Count how many devices are there. If err or no devices, set p=0 and print.
  if(cuda_try(ret = hipGetDeviceCount(&devs)) || devs == 0){
    stderr_out("hipGetDeviceCount error: %s\n", hipGetErrorString(ret));
    p = 0;
    goto print;
  }

  // Get the device properties of the last device
  dev = devs - 1;
  hipSetDevice(dev);
  hipGetDeviceProperties(&pr, dev);

  // Compute the number of concurrent blocks according to the formula 
  //
  //   # of SMs x # of warp schedulers per SM
  //
  p=pr.multiProcessorCount*how_many_warp_schedulers_per_SM(pr.major,pr.minor);

print:
  print_out("%u\n", p);

  return;
}


// This function prints out the number of independent blocks in the GPU,
// showing how the calculation was made: that is, # of SMs x # of warp sche-
// dulers per SM available in the given model.
//
void print_count_verbose(){
  hipError_t ret;                     // return value of CUDA calls
  int dev, devs;                       // number of devices
  hipDeviceProp_t pr;                   // device properties

  // Count how many devices are there. If err, return.
  if(cuda_try(ret = hipGetDeviceCount(&devs))){
    stderr_out("hipGetDeviceCount error: %s\n", hipGetErrorString(ret));
    return;
  }

  // If no devices, notify the user and return
  if(devs == 0){
    print_out("  (No CUDA-enabled GPUs in this machine.)\n");
    return;
  }

  // Get the device properties of the last device
  dev = devs - 1;
  hipSetDevice(dev);
  hipGetDeviceProperties(&pr, dev);

  // Show the calculation
  //
  //   # of SMs x # of warp schedulers per SM
  //
  print_out("  (%u SMs x %u warp schedulers per SM)\n",
    pr.multiProcessorCount,
    how_many_warp_schedulers_per_SM(pr.major, pr.minor));

  return;
}

// This function determines how many warp schedulers per SM are there in the
// GPU given ts major and minor architectural version.
// 
// Adapted from helper_cuda.h in the CUDA SDK:
//   (/usr/local/cuda/samples/common/inc/helper_cuda.h).
//
//   major, minor:                     major and minor architecture version
//
//   returns:                          number of warp schedulers per SM
//
int how_many_warp_schedulers_per_SM(int major, int minor){
  int i;
  sm_to_ws_t t[13];                   // Lookup table

  // Tesla architecture (1 warp scheduler per SM)
  t[0] .sm = 0x10;  t[0] .ws = 1;     // Tesla   (SM 1.0) G80 class
  t[1] .sm = 0x11;  t[1] .ws = 1;     // Tesla   (SM 1.1) G8X class
  t[2] .sm = 0x12;  t[2] .ws = 1;     // Tesla   (SM 1.2) G9X class
  t[3] .sm = 0x13;  t[3] .ws = 1;     // Tesla   (SM 1.3) GT200 class

  // Fermi architecture (2 warp schedulers per SM)
  t[4] .sm = 0x20;  t[4] .ws = 2;     // Fermi   (SM 2.0) GF100 class
  t[5] .sm = 0x21;  t[5] .ws = 2;     // Fermi   (SM 2.1) GF10x class

  // Kepler architecture (4 warp schedulers per SM)
  t[6] .sm = 0x30;  t[6] .ws = 4;     // Kepler  (SM 3.0) GK10x class
  t[7] .sm = 0x32;  t[7] .ws = 4;     // Kepler  (SM 3.2) GK10x class
  t[8] .sm = 0x35;  t[8] .ws = 4;     // Kepler  (SM 3.5) GK11x class
  t[9] .sm = 0x37;  t[9] .ws = 4;     // Kepler  (SM 3.7) GK21x class

  // Maxwell architecture (4 warp schedulers per SM)
  t[10].sm = 0x50;  t[10].ws = 4;     // Maxwell (SM 5.0) GM10x class
  t[11].sm = 0x52;  t[11].ws = 4;     // Maxwell (SM 5.2) GM20x class

  // Unknown architecture
  t[12].sm = -1;    t[12].ws = -1;    // Unknown

  for(i=0; i<13; i++){
    if(t[i].sm == ((major << 4) + minor)){
      return t[i].ws;
    }
  }
  return 0;
}

	.text
	.file	"how-many-concurrent-blocks.hip"
	.globl	main                            # -- Begin function main
	.type	main,@function
main:                                   # @main
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	pushq	%rax
	.cfi_def_cfa_offset 32
	.cfi_offset %rbx, -24
	.cfi_offset %rbp, -16
	movq	%rsi, %rbx
	movl	%edi, %ebp
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
	movl	$.L.str, %edx
	movl	%ebp, %edi
	movq	%rbx, %rsi
	callq	getopt
	cmpl	$118, %eax
	je	.LBB0_4
# %bb.2:                                #   in Loop: Header=BB0_1 Depth=1
	cmpl	$-1, %eax
	jne	.LBB0_1
# %bb.3:
	callq	_Z11print_countv
	jmp	.LBB0_5
.LBB0_4:
	callq	_Z19print_count_verbosev
.LBB0_5:
	xorl	%edi, %edi
	callq	exit
.Lfunc_end0:
	.size	main, .Lfunc_end0-main
	.cfi_endproc
                                        # -- End function
	.globl	_Z11print_countv                # -- Begin function _Z11print_countv
	.type	_Z11print_countv,@function
_Z11print_countv:                       # @_Z11print_countv
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	pushq	%r14
	.cfi_def_cfa_offset 24
	pushq	%rbx
	.cfi_def_cfa_offset 32
	subq	$1488, %rsp                     # imm = 0x5D0
	.cfi_def_cfa_offset 1520
	.cfi_offset %rbx, -32
	.cfi_offset %r14, -24
	.cfi_offset %rbp, -16
	leaq	12(%rsp), %rdi
	callq	hipGetDeviceCount
	testl	%eax, %eax
	jne	.LBB1_2
# %bb.1:
	movl	12(%rsp), %ebx
	testl	%ebx, %ebx
	je	.LBB1_2
# %bb.3:
	decl	%ebx
	movl	%ebx, %edi
	callq	hipSetDevice
	leaq	16(%rsp), %r14
	movq	%r14, %rdi
	movl	%ebx, %esi
	callq	hipGetDevicePropertiesR0600
	movl	388(%r14), %ebp
	movl	360(%r14), %edi
	movl	364(%r14), %esi
	callq	_Z31how_many_warp_schedulers_per_SMii
	movl	%eax, %ebx
	imull	%ebp, %ebx
.LBB1_4:
	movl	$.L.str.2, %edi
	movl	%ebx, %esi
	xorl	%eax, %eax
	callq	printf
	movq	stdout(%rip), %rdi
	callq	fflush
	addq	$1488, %rsp                     # imm = 0x5D0
	.cfi_def_cfa_offset 32
	popq	%rbx
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	retq
.LBB1_2:
	.cfi_def_cfa_offset 1520
	movq	stderr(%rip), %r14
	movl	%eax, %edi
	callq	hipGetErrorString
	xorl	%ebx, %ebx
	movl	$.L.str.1, %esi
	movq	%r14, %rdi
	movq	%rax, %rdx
	xorl	%eax, %eax
	callq	fprintf
	movq	stderr(%rip), %rdi
	callq	fflush
	jmp	.LBB1_4
.Lfunc_end1:
	.size	_Z11print_countv, .Lfunc_end1-_Z11print_countv
	.cfi_endproc
                                        # -- End function
	.globl	_Z19print_count_verbosev        # -- Begin function _Z19print_count_verbosev
	.type	_Z19print_count_verbosev,@function
_Z19print_count_verbosev:               # @_Z19print_count_verbosev
	.cfi_startproc
# %bb.0:
	pushq	%r14
	.cfi_def_cfa_offset 16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	subq	$1480, %rsp                     # imm = 0x5C8
	.cfi_def_cfa_offset 1504
	.cfi_offset %rbx, -24
	.cfi_offset %r14, -16
	leaq	4(%rsp), %rdi
	callq	hipGetDeviceCount
	testl	%eax, %eax
	jne	.LBB2_1
# %bb.2:
	movl	4(%rsp), %ebx
	testl	%ebx, %ebx
	je	.LBB2_3
# %bb.4:
	decl	%ebx
	movl	%ebx, %edi
	callq	hipSetDevice
	leaq	8(%rsp), %r14
	movq	%r14, %rdi
	movl	%ebx, %esi
	callq	hipGetDevicePropertiesR0600
	movl	388(%r14), %ebx
	movl	360(%r14), %edi
	movl	364(%r14), %esi
	callq	_Z31how_many_warp_schedulers_per_SMii
	movl	$.L.str.4, %edi
	movl	%ebx, %esi
	movl	%eax, %edx
	xorl	%eax, %eax
	callq	printf
	jmp	.LBB2_5
.LBB2_3:
	movl	$.Lstr, %edi
	callq	puts@PLT
.LBB2_5:
	movl	$stdout, %r14d
.LBB2_6:
	movq	(%r14), %rdi
	callq	fflush
	addq	$1480, %rsp                     # imm = 0x5C8
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	retq
.LBB2_1:
	.cfi_def_cfa_offset 1504
	movl	$stderr, %r14d
	movq	stderr(%rip), %rbx
	movl	%eax, %edi
	callq	hipGetErrorString
	movl	$.L.str.1, %esi
	movq	%rbx, %rdi
	movq	%rax, %rdx
	xorl	%eax, %eax
	callq	fprintf
	jmp	.LBB2_6
.Lfunc_end2:
	.size	_Z19print_count_verbosev, .Lfunc_end2-_Z19print_count_verbosev
	.cfi_endproc
                                        # -- End function
	.section	.rodata.cst16,"aM",@progbits,16
	.p2align	4, 0x0                          # -- Begin function _Z31how_many_warp_schedulers_per_SMii
.LCPI3_0:
	.long	16                              # 0x10
	.long	1                               # 0x1
	.long	17                              # 0x11
	.long	1                               # 0x1
.LCPI3_1:
	.long	18                              # 0x12
	.long	1                               # 0x1
	.long	19                              # 0x13
	.long	1                               # 0x1
.LCPI3_2:
	.long	32                              # 0x20
	.long	2                               # 0x2
	.long	33                              # 0x21
	.long	2                               # 0x2
.LCPI3_3:
	.long	48                              # 0x30
	.long	4                               # 0x4
	.long	50                              # 0x32
	.long	4                               # 0x4
.LCPI3_4:
	.long	53                              # 0x35
	.long	4                               # 0x4
	.long	55                              # 0x37
	.long	4                               # 0x4
.LCPI3_5:
	.long	80                              # 0x50
	.long	4                               # 0x4
	.long	82                              # 0x52
	.long	4                               # 0x4
	.text
	.globl	_Z31how_many_warp_schedulers_per_SMii
	.type	_Z31how_many_warp_schedulers_per_SMii,@function
_Z31how_many_warp_schedulers_per_SMii:  # @_Z31how_many_warp_schedulers_per_SMii
	.cfi_startproc
# %bb.0:
	movaps	.LCPI3_0(%rip), %xmm0           # xmm0 = [16,1,17,1]
	movaps	%xmm0, -104(%rsp)
	movaps	.LCPI3_1(%rip), %xmm0           # xmm0 = [18,1,19,1]
	movaps	%xmm0, -88(%rsp)
	movaps	.LCPI3_2(%rip), %xmm0           # xmm0 = [32,2,33,2]
	movaps	%xmm0, -72(%rsp)
	movaps	.LCPI3_3(%rip), %xmm0           # xmm0 = [48,4,50,4]
	movaps	%xmm0, -56(%rsp)
	movaps	.LCPI3_4(%rip), %xmm0           # xmm0 = [53,4,55,4]
	movaps	%xmm0, -40(%rsp)
	movaps	.LCPI3_5(%rip), %xmm0           # xmm0 = [80,4,82,4]
	movaps	%xmm0, -24(%rsp)
	movq	$-1, -8(%rsp)
	shll	$4, %edi
	addl	%esi, %edi
	xorl	%eax, %eax
.LBB3_1:                                # =>This Inner Loop Header: Depth=1
	cmpl	%edi, -104(%rsp,%rax,8)
	je	.LBB3_4
# %bb.2:                                #   in Loop: Header=BB3_1 Depth=1
	incq	%rax
	cmpq	$13, %rax
	jne	.LBB3_1
# %bb.3:
	xorl	%eax, %eax
	retq
.LBB3_4:
	movl	-100(%rsp,%rax,8), %eax
	retq
.Lfunc_end3:
	.size	_Z31how_many_warp_schedulers_per_SMii, .Lfunc_end3-_Z31how_many_warp_schedulers_per_SMii
	.cfi_endproc
                                        # -- End function
	.type	.L.str,@object                  # @.str
	.section	.rodata.str1.1,"aMS",@progbits,1
.L.str:
	.asciz	"v"
	.size	.L.str, 2

	.type	.L.str.1,@object                # @.str.1
.L.str.1:
	.asciz	"hipGetDeviceCount error: %s\n"
	.size	.L.str.1, 29

	.type	.L.str.2,@object                # @.str.2
.L.str.2:
	.asciz	"%u\n"
	.size	.L.str.2, 4

	.type	.L.str.4,@object                # @.str.4
.L.str.4:
	.asciz	"  (%u SMs x %u warp schedulers per SM)\n"
	.size	.L.str.4, 40

	.type	__hip_cuid_,@object             # @__hip_cuid_
	.bss
	.globl	__hip_cuid_
__hip_cuid_:
	.byte	0                               # 0x0
	.size	__hip_cuid_, 1

	.type	.Lstr,@object                   # @str
	.section	.rodata.str1.1,"aMS",@progbits,1
.Lstr:
	.asciz	"  (No CUDA-enabled GPUs in this machine.)"
	.size	.Lstr, 42

	.ident	"AMD clang version 18.0.0git (https://github.com/RadeonOpenCompute/llvm-project roc-6.3.2 25012 e5bf7e55c91490b07c49d8960fa7983d864936c4)"
	.section	".note.GNU-stack","",@progbits
	.addrsig
	.addrsig_sym __hip_cuid_

	.text
	.p2alignl 7, 3214868480
	.fill 96, 4, 3214868480
	.type	__hip_cuid_,@object             ; @__hip_cuid_
	.section	.bss,"aw",@nobits
	.globl	__hip_cuid_
__hip_cuid_:
	.byte	0                               ; 0x0
	.size	__hip_cuid_, 1

	.ident	"AMD clang version 18.0.0git (https://github.com/RadeonOpenCompute/llvm-project roc-6.3.2 25012 e5bf7e55c91490b07c49d8960fa7983d864936c4)"
	.section	".note.GNU-stack","",@progbits
	.addrsig
	.addrsig_sym __hip_cuid_
	.amdgcn_target "amdgcn-amd-amdhsa--gfx1100"
	.amdgpu_metadata
---
amdhsa.kernels:  []
amdhsa.target:   amdgcn-amd-amdhsa--gfx1100
amdhsa.version:
  - 1
  - 2
...

	.end_amdgpu_metadata
