[LLVMdev] Create "appending" section that can be partially dead stripped

Jonas Maebe
Tue, 05 Aug 2014 14:34:11 -0000

On 04 Aug 2014, at 09:27, Reid Kleckner wrote:

> On Sat, Aug 2, 2014 at 7:51 AM, Jonas Maebe
> <jonas.maebe at elis.ugent.be>
> wrote:
>
>> On 01/08/14 19:37, Reid Kleckner wrote:
>>
>>> What happens if you drop appending linkage?  I think it will just
>>> work,
>>> since you are already using a custom section, which will ensure
>>> that all
>>> the data appears contiguously in memory.
>>
>> Thanks for the suggestion, but it still puts everything in a single
>> .section statement.
>
> Try giving the globals linkonce_odr linkage instead of external
> linkage
> manually?  This is essentially the effect of -fdata-sections, except
> it
> happens later during codegen.

That one indeed works, thanks! (provided I process the .ll file with
optimisations enabled).

Regarding the question whether the optimisers and analyses will deal
correctly with me iterating over all of the elements in such a
section, at least at first sight it seems that the test below looks
fine when processed with full optimisations. That's of course no proof
that there won't be any problems in any case.

However, I'm not sure how to add a symbol without data at the start
and end of the section. Adding a [i32 x 0]-typed symbol still inserts
a byte (see the @arrstart/@arrstop). I can't work with alias
declarations to the first and last element, since then the first and
last element will always be considered live.


Jonas

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-
i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-
f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

define i32 @main() {
Entry:
  %sumvar = alloca i32

; make the second and third element live by directly referring them
  %eleptr1 = getelementptr [2 x i32]* @arr2, i64 0, i32 0
  %eleptr2 = getelementptr [2 x i32]* @arr3, i64 0, i32 0
  %ele1 = load i32* %eleptr1
  %ele2 = load i32* %eleptr2
  %sum1 = add i32 %ele1, %ele2
  store i32 %sum1, i32* %sumvar

; now loop over the entire array by using @arrstart and @arrstop
  %loopstop = ptrtoint [0 x i32]* @arrstop to i64
  %loopstart = ptrtoint [0 x i32]* @arrstart to i64
  %loopcount = sub i64 %loopstop, %loopstart
  %looparrinit = bitcast [0 x i32]* @arrstart to i32*
  br label %LoopStart

; sum all elements in the array
LoopStart:
  %looparr = phi i32* [%looparrinit, %Entry], [%looparrnext, %LoopBody]
  %loopcond = icmp eq i64 %loopcount, 0
  br i1 %loopcond, label %LoopEnd, label %LoopBody
LoopBody:
  %val = load i32* %looparr
  %sum2 = load i32* %sumvar
  %sum3 = add i32 %val, %sum2
  store i32 %sum3, i32* %sumvar
  %looparrnext = getelementptr i32* %looparr, i64 1
br label %LoopStart

; return the sum
LoopEnd:
  %retval = load i32* %sumvar
  ret i32 %retval
}

; this declaration inserts a 0 byte
@arrstart = global [0 x i32] [ ], section "mytest"

@arr1 = linkonce_odr global [2 x i32] [
   i32 1,
   i32 2
], section "mytest"

@arr2 = linkonce_odr global [2 x i32] [
   i32 3,
   i32 4
], section "mytest"

@arr3 = linkonce_odr global [2 x i32] [
   i32 5,
   i32 6
], section "mytest"

; this declaration inserts a 0 byte
@arrstop = global [0 x i32] [ ], section "mytest"