[LLVMdev] Handling of thread_local globals by llc -march=cpp

o.j.sivart at gmail.com o.j.sivart at gmail.com
Wed May 12 21:53:51 PDT 2010


Hi all,

I've been exploring thread local globals in llvm and as part of this investigation I ran llc -march=cpp over a trivial llvm bc file which uses thread local storage for a global. For some reason llc -march=cpp seems to ignore the thread_local and produce code to create a standard global. Is this expected behaviour, a known limitation, or otherwise?

Thanks in advance.

Details are as follows.

The llvm bc I'm using (which clang produced from a simple c source file, thread_local.c, that has a __thread global, a, and a single function, f, which returns the value of the thread local global) is:

; ModuleID = 'thread_local.c'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
target triple = "i386-pc-linux-gnu"

@a = thread_local global i32 1, align 4           ; <i32*> [#uses=1]

define i32 @f() nounwind {
entry:
  %retval = alloca i32, align 4                   ; <i32*> [#uses=2]
  %tmp = load i32* @a                             ; <i32> [#uses=1]
  store i32 %tmp, i32* %retval
  %0 = load i32* %retval                          ; <i32> [#uses=1]
  ret i32 %0
}

Within the cpp file the relevant code to create and initialise the global is:

  GlobalVariable* gvar_int32_a = new GlobalVariable(/*Module=*/*mod, 
  /*Type=*/IntegerType::get(mod->getContext(), 32),
  /*isConstant=*/false,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Initializer=*/0, // has initializer, specified below
  /*Name=*/"a");
  gvar_int32_a->setAlignment(4);
  
  // Constant Definitions
  ConstantInt* const_int32_2 = ConstantInt::get(mod->getContext(), APInt(32, StringRef("1"), 10));
  
  // Global Variable Definitions
  gvar_int32_a->setInitializer(const_int32_2);

As you can see no actual parameter is provided for the optional formal ThreadLocal parameter of the GlobalVariable constructor; it instead then gets the default value of false. Compiling the cpp file and executing it to check the output of running the createPrintModulePass confirms that the llvm IR produced does not create a thread local global variable:

; ModuleID = 'thread_local.s'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
target triple = "i386-pc-linux-gnu"

@a = global i32 1, align 4           ; <i32*> [#uses=1]

define i32 @f() nounwind {
entry:
  %retval = alloca i32, align 4                   ; <i32*> [#uses=2]
  %tmp = load i32* @a                             ; <i32> [#uses=1]
  store i32 %tmp, i32* %retval
  %0 = load i32* %retval                          ; <i32> [#uses=1]
  ret i32 %0
}



More information about the llvm-dev mailing list