Skip to content

LLVM passes may insert intrinsic calls with arguments of type "metadata" #1631

Description

@haved

The metadata type is not supported in jlm. It is not a real datatype, but it can occur in the argument list of instrisics:

declare void @llvm.experimental.noalias.scope.decl(metadata)

; And later, inside a function:
tail call void @llvm.experimental.noalias.scope.decl(metadata !11)
Click this drop-down to see an example C file where this occurs

File lzma_encoder_optimum_normal.c:

#include <stdint.h>

struct A {
    uint32_t a;
    uint32_t* b;
};

void opaque(struct A *mf, uint32_t * count);

uint32_t helper1(struct A *restrict mf, uint32_t * back_res, uint32_t * len_res)
{
    if (mf->a) {
        uint32_t matches_count;
		opaque(mf, &matches_count);
	}
	return 20;
}

void f(struct A * mf, uint32_t * back_res, uint32_t * len_res)
{
	helper1(mf, back_res, len_res);
}

Compile with

"`llvm-config-18 --bindir`/clang" -Os lzma_encoder_optimum_normal.c -S -emit-llvm -o leon.ll
jlm-opt leon.ll -o leon-jlm-opt.ll

Supporting metadata properly would mean adding support for the general metadata structure in LLVM, which is all those lines we see at the bottom of files:

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{!"clang version 18.1.8 (git@github.com:llvm/llvm-project.git 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)"}
!5 = !{!6, !7, i64 0}
!6 = !{!"A", !7, i64 0, !10, i64 8}
!7 = !{!"int", !8, i64 0}
!8 = !{!"omnipotent char", !9, i64 0}
!9 = !{!"Simple C/C++ TBAA"}
!10 = !{!"any pointer", !8, i64 0}
!11 = !{!12}
!12 = distinct !{!12, !13, !"helper1: %mf"}
!13 = distinct !{!13, !"helper1"}

As a quicker solution, I think we should just filter out these function declarations and calls. I have only seen this one intrinsic using metadata in the wild so far.

In addition to this noalias scope metadata intrinsic, I also see other intrinsics:

declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)

while these latter ones are technically supported by jlm, they are treated as calls to external functions, causing their pointer arguments to escape the module.

I think we should create a small curated list of function names that we strip away in the frontend (both function declarations and calls).
Unless we actually write the code to properly make use of these intrinsics, they only make the compiler less able to reason about code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions