Hello everyone,
I would like to propose to adding a code model attribute for global variable, which can override the target’s default code model.
Motivation
There is an edge case where only certain global variables require larger code models, while the rest can default to smaller ones, which can effectively reduce overhead.
For linux kernel module percpu case of LoongArch:
static __attribute__((section(".data..percpu" ""))) int pcpu;
int fun(void)
{
return pcpu;
}
After static linking, a small
code model code is generated to access the pcpu
variable, which can fully access the pcpu
variable in the same link unit. The corner issue with kernel modules is that after dynamic linking, the actual location of the pcpu
variables will be so far away from the code that the default code model (small) doesn’t work. This only happens for per-cpu variables, changing the code model for variables instead of all will help reduce overhead.
Proposal
In a previous discussion created by @xen0n, @aeubanks proposed adding a code model attribute to global variables. Backends will need to be updated to respect this.
@pcpu = internal global i32 0, section ".data..percpu", code_model "large"
How it works?
For the LoongArch case, the backend generated a large
code model for the pcpu_large
variable.
static __attribute__((section(".data..percpu" ""))) int pcpu_small;
int fun_small(void)
{
return pcpu_small;
}
static __attribute__((section(".data..percpu" ""))) __attribute__((model("large")) int pcpu_large;
int fun_large(void)
{
return pcpu_large;
}
@pcpu_small= internal global i32 0, align 4
define dso_local signext i32 @fun_small() #0 {
; CHECK-LABEL: fun_small:
; CHECK: # %bb.0:
; CHECK-NEXT: pcalau12i $a0, %pc_hi20(pcpu_small)
; CHECK-NEXT: addi.d $a0, $a0, %pc_lo12(pcpu_small)
; CHECK-NEXT: ld.w $a0, $a0, 0
; CHECK-NEXT: ret
%1 = load i32, ptr @pcpu_small, align 4
ret i32 %1
}
@pcpu_large = internal global i32 0, code_model "large", align 4
define dso_local signext i32 @fun_large() #0 {
; CHECK-LABEL: fun_large:
; CHECK: # %bb.0:
; CHECK-NEXT: pcalau12i $a0, %pc_hi20(pcpu_large)
; CHECK-NEXT: addi.d $a1, $zero, %pc_lo12(pcpu_large)
; CHECK-NEXT: lu32i.d $a1, %pc64_lo20(pcpu_large)
; CHECK-NEXT: lu52i.d $a1, $a1, %pc64_hi12(pcpu_large)
; CHECK-NEXT: add.d $a0, $a1, $a0
; CHECK-NEXT: ld.w $a0, $a0, 0
; CHECK-NEXT: ret
%1 = load i32, ptr @pcpu_large, align 4
ret i32 %1
}
Pull requests
Part 1/3: [llvm][IR] Add per-global code model attribute
Part 2/3: [clang] Add per-global code model attribute
Part 3/3: [llvm][LoongArch] Get the code model from the global object