Here is the minimum repro. repro.c: a, b; void *mempcpy(void *, *, long); c(*) { char *d = mempcpy(d, a, b); *d = '\0'; c(d); } repro.sh: clang -mllvm -attributor-enable=module -O2 repro.c error: Wrong types for attribute: inalloca nest noalias nocapture noundef nonnull readnone readonly signext zeroext byref(void) byval(void) preallocated(void) sret(void) align 1 dereferenceable(1) dereferenceable_or_null(1) tail call nonnull dereferenceable(1) void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 undef, i8* readonly align 1 %3, i64 %conv1, i1 false) #3 in function c fatal error: error in backend: Broken function found, compilation aborted! clang-12: error: clang frontend command failed with exit code 70 (use -v to see invocation)
This is a bug, but not an Attributor one ;) https://godbolt.org/z/vhsKPf Looking where the attribute needs to be dropped now.
Somewhere in instcombine but I didn't find it immediately, I hope someone knows and gives an update tomorrow.
Thanks for pointing it out. I'll give it a try.
(In reply to Zequan Wu from comment #3) > Thanks for pointing it out. I'll give it a try. It might be as simple as this https://reviews.llvm.org/D87306 I haven't tried it though. We might not need to know where it comes from ;)
Minimal test: define i32 @PR48810(i32* %x) { %r = call dereferenceable(1) i8* @mempcpy(i8* undef, i32* null, i64 undef) ret i32 undef } declare i8* @mempcpy(i8*, i32*, i64) ------------------------------------------------------------------------------- Instcombine tries to convert that to a memcpy intrinsic: Value *LibCallSimplifier::optimizeMemPCpy(CallInst *CI, IRBuilderBase &B) { Value *Dst = CI->getArgOperand(0); Value *N = CI->getArgOperand(2); // mempcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n), x + n CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), CI->getArgOperand(1), Align(1), N); NewCI->setAttributes(CI->getAttributes()); ------------------------------------------------------------------------------- But IIUC, we can't apply "dereferenceable" to a void return.
(In reply to Sanjay Patel from comment #5) > Minimal test: > > define i32 @PR48810(i32* %x) { > %r = call dereferenceable(1) i8* @mempcpy(i8* undef, i32* null, i64 undef) > ret i32 undef > } > > declare i8* @mempcpy(i8*, i32*, i64) > > ----------------------------------------------------------------------------- > -- > > Instcombine tries to convert that to a memcpy intrinsic: > > Value *LibCallSimplifier::optimizeMemPCpy(CallInst *CI, IRBuilderBase &B) { > Value *Dst = CI->getArgOperand(0); > Value *N = CI->getArgOperand(2); > // mempcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n), x + n > CallInst *NewCI = > B.CreateMemCpy(Dst, Align(1), CI->getArgOperand(1), Align(1), N); > NewCI->setAttributes(CI->getAttributes()); > > ----------------------------------------------------------------------------- > -- > > But IIUC, we can't apply "dereferenceable" to a void return. We need something like this (taken from InstCombineCalls.cpp:2281): ``` // Get any return attributes. AttrBuilder RAttrs(CallerPAL, AttributeList::ReturnIndex); // If the return value is not being used, the type may not be compatible // with the existing attributes. Wipe out any problematic attributes. RAttrs.remove(AttributeFuncs::typeIncompatible(NewRetTy)); ```
Thanks for the pointer! Zequan, are you working on this? If not, I can post a patch for review.
No, I am not. Feel free to post a patch. Thanks
https://reviews.llvm.org/D95088
Minimally fixed the crash: https://reviews.llvm.org/rG070af1b7887f
Thanks for the quick fix.