Thanks to visit codestin.com
Credit goes to github.com

Skip to content

LLVM: Use LLVM pointers for C# pointers #16251

@EgorBo

Description

@EgorBo

For

[MethodImpl(MethodImplOptions.NoInlining)]
public static byte GetElement(byte* array) 
{
    return array[0];
}

We generate the following LLVM IR (-O0):

; Function Attrs: noinline uwtable
define monocc i8 @"Program:GetElement (byte*)"(i64* %arg_array) #0 {
BB0:
  br label %BB3

BB3:                                              ; preds = %BB0
  br label %BB2

BB2:                                              ; preds = %BB3
  %0 = bitcast i64* %arg_array to i8*
  %1 = load i8, i8* %0
  %2 = zext i8 %1 to i32
  %3 = trunc i32 %2 to i8
  %t18 = zext i8 %3 to i32
  br label %BB4

BB4:                                              ; preds = %BB2
  br label %BB1

BB1:                                              ; preds = %BB4
  %4 = trunc i32 %t18 to i8
  ret i8 %4
}

As you can see the argument is i64* (long*) which then is bitcasted to i8* So why don't we use real pointers here? For this case it's fine - LLVM is able to optimize it to a single mov but in more complicated scenarios it seems it's a problem:

[MethodImpl(MethodImplOptions.NoInlining)]
public static void ZeroArray(byte* array, int len) 
{
    for (int i=0; i<len; i++)
    {
        array[i] = 0;
    }
}

Ideally this code should be optimized to a single memset call, e.g. C++ does it:

  1. C++ to LLVM IR: https://godbolt.org/z/JP7j7l
  2. opt -O1 for that LLVM IR: https://godbolt.org/z/VEHQVp recognizes memset (as you can see Induction Variable Simplification pass did the magic trick)
  3. LLVM IR to asm (llc) https://godbolt.org/z/4B_3HK

But the LLVM IR that mono generates can not be optimized due to redundant bitcast/inttoptr/ptrtoint operations: https://godbolt.org/z/rC0v3Z

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions