RFC: Replacing publicly accessible class IDs with getters

Hello all,

In the process of porting the Polly plug-in to Windows we encountered a couple of issues stemming from the use (within Polly) of global data from LLVM.

By far the most common occurrence of this is the definition by a class of a publicly accessible static ID, the address of which is used to uniquely identify the class. For example

class AliasAnalysis {

public:
static char ID; // Class identification, replacement for typeinfo

};

This turns out to be problematic on Windows for two reasons:

  1. We found that Visual Studio actually defines two copies of the ID, one within the clang executable and another within the Polly library. This results in Polly being unable to identify LLVM passes. (This seems like a bug in Visual Studio, but we could not find a resolution other than changing LLVM as noted below).
  2. We chose to use delay loading for symbols imported by Polly from clang. This allows the Polly dll to be loaded into any executable that provides the required symbols. However delay loading precludes the importing of data[1].

We would like to resolve these issues by replacing public access of the ID with a getter:

class AliasAnalysis {

private:
static char ID; // Class identification, replacement for typeinfo
public:``
```static const void *getClassPassID(); };`

Thoughts?

Matthew Curtis

[1]

I think that would be O.K., but why getClassPassID return "const void
*" not just "char"?

Regards,
chenwj

Hello all,

In the process of porting the Polly plug-in to Windows we encountered a couple
of issues stemming from the use (within Polly) of global data from LLVM.

By far the most common occurrence of this is the definition by a class of a
publicly accessible static ID, the address of which is used to uniquely
identify the class. For example

     class AliasAnalysis {

     public:
       static char ID; // Class identification, replacement for typeinfo

     };

This turns out to be problematic on Windows for two reasons:

1) We found that Visual Studio actually defines two copies of the ID, one
within the clang executable and another within the Polly library. This results
in Polly being unable to identify LLVM passes. (This seems like a bug in Visual
Studio, but we could not find a resolution other than changing LLVM as noted
below).
2) We chose to use delay loading for symbols imported by Polly from clang. This
allows the Polly dll to be loaded into any executable that provides the
required symbols. However delay loading precludes the importing of data[1].

We would like to resolve these issues by replacing public access of the ID with
a getter:

     class AliasAnalysis {

     private:
       static char ID; // Class identification, replacement for typeinfo

     public:
       static const void *getClassPassID();
     };

   I think that would be O.K., but why getClassPassID return "const void
*" not just "char"?

The class is actually identified by the address of 'ID'. The value of 'ID' is irrelevant. So where it is currently used you will amost always find '&ClassName::ID'.

Hi all,

I'm trying to use the newly added (in LLVM 3.2) NVPTX backend for producing PTX (Parallel Thread eXecution) assembly from simple C programs.

While using llc with -march for mips and x86 works, -march=nvptx doesn't work. This seems reasonable since I can see that the libLLVMNVPTXAsmPrinter.a library is about 500 bytes (thus empty). However, the strange thing is that AsmPrinter code can be found in the NVPTX backend directory. I would expect that this code would be compiled to the corresponding assembly printing library.

Has anyone had similar problems with the NVPTX backend? Shouldn't this code be linked to the AsmPrinter library for NVPTX (already)?

BTW I've built LLVM with mingw (strange mixture of gcc-3.4.5 and g++-4.6.1). Native compilation, MIPS backend and other things that i've tested, all work properly.

Any help is appreciated.

Best regards,
Nikolaos Kavvadias

Hi all,

I'm trying to use the newly added (in LLVM 3.2) NVPTX backend for
producing PTX (Parallel Thread eXecution) assembly from simple C programs.

While using llc with -march for mips and x86 works, -march=nvptx doesn't
work. This seems reasonable since I can see that the
libLLVMNVPTXAsmPrinter.a library is about 500 bytes (thus empty). However,
the strange thing is that AsmPrinter code can be found in the NVPTX backend
directory. I would expect that this code would be compiled to the
corresponding assembly printing library.

Has anyone had similar problems with the NVPTX backend? Shouldn't this
code be linked to the AsmPrinter library for NVPTX (already)?

What do you mean by "doesn't work"? The AsmPrinter library really houses
the MCInst printer, which isn't implemented for NVPTX yet. The older
assembly printer works just fine. This is transparent to users. The NVPTX
target can be used just like MIPS and X86 with llc (and library users).

Is llc saying nvptx is an invalid target? If so, you probably built LLVM
without NVPTX.

BTW I've built LLVM with mingw (strange mixture of gcc-3.4.5 and
g++-4.6.1). Native compilation, MIPS backend and other things that i've
tested, all work properly.

Perhaps this "strange mixture" is causing some symbol errors somewhere.
Can you post the exact sequence of steps you used to build LLVM, along with
the llc command-line that fails for you?

Hi Justin,

Has anyone had similar problems with the NVPTX backend? Shouldn't this
code be linked to the AsmPrinter library for NVPTX (already)?

What do you mean by "doesn't work"? The AsmPrinter library really houses
the MCInst printer, which isn't implemented for NVPTX yet. The older
assembly printer works just fine. This is transparent to users. The NVPTX
target can be used just like MIPS and X86 with llc (and library users).

Is llc saying nvptx is an invalid target? If so, you probably built LLVM
without NVPTX.

I've used -enable-targets=all, and all libLLVMNVPTX*.a libs were produced. However, the AsmPrinter one looks dummy.

Further, nvptx appears as a registered target when running llc --version.

llc doesn't complain, but just "runs" forever with apparently no output

BTW I've built LLVM with mingw (strange mixture of gcc-3.4.5 and
g++-4.6.1). Native compilation, MIPS backend and other things that i've
tested, all work properly.

Perhaps this "strange mixture" is causing some symbol errors somewhere.
Can you post the exact sequence of steps you used to build LLVM, along with
the llc command-line that fails for you?

My configuration options were:

--prefix=/my/local/path/or/so --enable-shared --enable-targets=all --enable-optimized --disable-libffi --disable-debug-runtime --disable-assertions --disable-expensive-checks

Following configuration i did the typical make and make install (to a selected path by --prefix.

Best regards
Nikolaos Kavvadias

Hi Justin,

Has anyone had similar problems with the NVPTX backend? Shouldn't this

code be linked to the AsmPrinter library for NVPTX (already)?

What do you mean by "doesn't work"? The AsmPrinter library really houses
the MCInst printer, which isn't implemented for NVPTX yet. The older
assembly printer works just fine. This is transparent to users. The
NVPTX
target can be used just like MIPS and X86 with llc (and library users).

Is llc saying nvptx is an invalid target? If so, you probably built LLVM
without NVPTX.

I've used -enable-targets=all, and all libLLVMNVPTX*.a libs were produced.
However, the AsmPrinter one looks dummy.

Further, nvptx appears as a registered target when running llc --version.

llc doesn't complain, but just "runs" forever with apparently no output

Can you post the llc command line you're using? Can you post an LLVM IR
file that causes this behavior?

Hi Nikolaos,

Following commands work great for me.
$ clang -S -emit-llvm -target nvptx -x cl -include clc/clctypes.h …/data-types/scalar.cl
$ llc -mcpu=sm_30 scalar.s

You can follow Justin’s blog [1]. It helped me a lot to understand where to start.

[1] http://jholewinski.org/blog/llvm-3-0-ptx-backend/

Best,
Ankur

Hi,

Can you post the llc command line you're using? Can you post an LLVM IR
file that causes this behavior?

yes:

${LLVM_PATH}/bin/llc -o helloworld.s -march=nvptx helloworld.ll

where LLVM_PATH my local installation path for LLVM.

Also attaching helloworld.c:

#include <stdio.h>

int main(void) {
   printf("Hello World!\n");
   return 0;
}

and helloworld.ll:

; ModuleID = 'helloworld.c'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S32"
target triple = "i686-w64-mingw32"

@str = private unnamed_addr constant [13 x i8] c"Hello World!\00"

define i32 @main() nounwind {
   %puts = tail call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @str, i32 0, i32 0))
   ret i32 0
}

declare i32 @puts(i8* nocapture) nounwind

For instance, the "mips" target produces this:

  .section .mdebug.abi32
  .previous
  .file "helloworld.ll"
  .text
  .globl main
  .align 2
  .type main,@function
  .set nomips16 # @main
  .ent main
main:
  .frame $sp,24,$ra
  .mask 0x80000000,-4
  .fmask 0x00000000,0
  .set noreorder
  .set nomacro
  .set noat
# BB#0:
  lui $2, %hi(_gp_disp)
  addiu $2, $2, %lo(_gp_disp)
  addiu $sp, $sp, -24
  sw $ra, 20($sp) # 4-byte Folded Spill
  addu $gp, $2, $25
  lw $1, %got($str)($gp)
  lw $25, %call16(puts)($gp)
  jalr $25
  addiu $4, $1, %lo($str)
  addiu $2, $zero, 0
  lw $ra, 20($sp) # 4-byte Folded Reload
  jr $ra
  addiu $sp, $sp, 24
  .set at
  .set macro
  .set reorder
  .end main
$tmp2:
  .size main, ($tmp2)-main

  .type $str,@object # @str
  .section .rodata.str1.4,"aMS",@progbits,1
  .align 2
$str:
  .asciz "Hello World!"
  .size $str, 13

Best regards
Nikolaos Kavvadias

Alright, couple of points here:

  1. Address space 0 is invalid for global variables. This is causing a crash in llc where we use llvm_unreachable() on this case. This is most likely why you’re seeing llc run forever. The fix for this is to use address space 1 for globals, which puts them into PTX global memory. On our side, we should provide a meaningful error message in this case.

  2. The stdio.h header you’re using has no chance of producing IR that is valid for NVPTX. In this case, printf gets translated into a call to puts(), which will be undefined if you try to execute the PTX.

I’m putting together some documentation on using the back-end; hopefully I’ll have something ready soon.

Hi Justin,

thank you for your time, you were right!

This helloworld.c (no I/O calls):

int main(void) {return 0;}

produces the following PTX output:

//
// Generated by LLVM NVPTX Back-End
//

.version 3.1
.target sm_10, texmode_independent
.address_size 32

  // .globl main
.func (.reg .b32 func_retval0) main(

) // @main
{
  .reg .pred %p<396>;
  .reg .s16 %rc<396>;
  .reg .s16 %rs<396>;
  .reg .s32 %r<396>;
  .reg .s64 %rl<396>;
  .reg .f32 %f<396>;
  .reg .f64 %fl<396>;

// BB#0:
  mov.u32 %r0, 0;
  mov.b32 func_retval0, %r0;
  ret;
}

Best regards
Nikolaos Kavvadias

Quoting Justin Holewinski <justin.holewinski@gmail.com>:

Hi ankur

thanks for the heads-up.

Best regards
Nikolaos Kavvadias
Quoting ankur deshwal <a.s.deshwal@gmail.com>:

Understood. Maybe you can submit patch to llvm-commits to get more
attention, or ping someone who maintains this things.

Regards,
chenwj

Hi Matthew,

In the process of porting the Polly plug-in to Windows we encountered a couple
of issues stemming from the use (within Polly) of global data from LLVM.

By far the most common occurrence of this is the definition by a class of a
publicly accessible static ID, the address of which is used to uniquely identify
the class. For example

    class AliasAnalysis {

    public:
       static char ID; // Class identification, replacement for typeinfo

    };

This turns out to be problematic on Windows for two reasons:

1) We found that Visual Studio actually defines two copies of the ID, one within
the clang executable and another within the Polly library. This results in Polly
being unable to identify LLVM passes. (This seems like a bug in Visual Studio,
but we could not find a resolution other than changing LLVM as noted below).

this sounds like the kind of thing you get on linux if both clang and polly are
linked with the same LLVM libraries. Are you sure it isn't something analogous
on windows?

2) We chose to use delay loading for symbols imported by Polly from clang. This
allows the Polly dll to be loaded into any executable that provides the required
symbols. However delay loading precludes the importing of data[1].

We would like to resolve these issues by replacing public access of the ID with
a getter:

    class AliasAnalysis {

    private:
       static char ID; // Class identification, replacement for typeinfo

    public:
       static const void *getClassPassID();
    };

That said, this looks pretty reasonable to me.

Ciao, Duncan.