Small problem with intrinsics

Hello,

I'm getting the impression that I'm misunderstanding something about
intrinsics. I have the following reduced testcase in mind:

declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind

define void @foo(i8* %a, i8* %b, i32 %c, i32 %d) {
entry:
  ;call void @llvm.memcpy.i32( i8* %a, i8* %b, i32 %c, i32 %d )
  ;call void @llvm.memcpy.i32( i8* %a, i8* %b, i32 0, i32 0 )
  ret void
}

I compile this with

llvm-as memcpy-intrinsic.ll -f -o memcpy-intrinsic.bc && llc -f -o
memcpy-intrinsic.s memcpy-intrinsic.bc

Now, if I uncomment the lowermost memcpy, this produces no errors. If I
uncomment the uppermost memcpy instead, I get during lcc:

llc: /var/bcoppens/llvm/llvm-svn/llvm/include/llvm/Support/Casting.h:199:
typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&) [with X =
llvm::ConstantInt, Y = llvm::Value*]: Assertion `isa<X>(Val) && "cast<Ty>()
argument of incompatible type!"' failed.

I can't see why this would happen. Both times, the function signature I call
is seemingly correct to my eyes. Does anybody see what I'm missing here?

Thanks,
Bart Coppens

Hi,

I'm getting the impression that I'm misunderstanding something about
intrinsics. I have the following reduced testcase in mind:

declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind

define void @foo(i8* %a, i8* %b, i32 %c, i32 %d) {
entry:
  ;call void @llvm.memcpy.i32( i8* %a, i8* %b, i32 %c, i32 %d )

I'm pretty sure that the alignment argument has to be a constant.

Ciao,

Duncan.

Hi Bart,

I guess that's because the value of the last argument of llvm.memcpy has to be known at compile time.

Nicolas

Bart Coppens wrote:

Hi Nicolas,

I guess that's because the value of the last argument of llvm.memcpy has
to be known at compile time.

Hmmm ok, that's understandable, but it's also a bit of a problem for me. I am
writing a pass that creates a 'shadow' copy of each function, so that I can
do some bookkeeping with it, and then call the original function afterwards.
This would include intrinsics like memcpy.

Now, would it be possible to programmatically determine which arguments are
required to be constants? Then I would be able to partially evaluate my
custom function, so that multiple versions would be emitted, each with the
right constants in their call to memcpy.

(Given that LLVM seems to be pretty statically typed, it's rather confusing
that this kind of restriction isn't at least annotated in the user-visible
type, or isn't noticed by llvm-as.)

Thanks,
Bart Coppens

Hi Nicolas,

I guess that’s because the value of the last argument of llvm.memcpy hasto be known at compile time.

Hmmm ok, that’s understandable, but it’s also a bit of a problem for me. I am writing a pass that creates a ‘shadow’ copy of each function, so that I can do some bookkeeping with it, and then call the original function afterwards. This would include intrinsics like memcpy.

Now, would it be possible to programmatically determine which arguments are required to be constants? Then I would be able to partially evaluate my custom function, so that multiple versions would be emitted, each with the right constants in their call to memcpy.

(Given that LLVM seems to be pretty statically typed, it’s rather confusing that this kind of restriction isn’t at least annotated in the user-visible type, or isn’t noticed by llvm-as.)

Intrinsics are special; they’re really extensions to the LLVM IR, and you can’t make any general assumptions about them. As an extreme example, @llvm.gcroot generates no code whatsoever at the call site, but influences codegen; you can’t do AOP transformations upon it as you propose without utterly breaking its semantics.

The only safe course is to exclude call or invoke instructions where getIntrinsicID() != 0 from your transformation. For intrinsics that you do recognize, you can special-case them. In this case, you can do the equivalent of:

template
mymemcpy(…) {
@llvm.memcpy(…, align);
}

— Gordon

Yes, in that case getIntrinsicID will suffice for me. Thanks for all the fast
replies :slight_smile:

Bart Coppens