diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -3064,12 +3064,9 @@ if (!CastInst::isBitOrNoopPointerCastable(ActTy, ParamTy, DL)) return false; // Cannot transform this parameter value. - if (AttrBuilder(FT->getContext(), CallerPAL.getParamAttrs(i)) - .overlaps(AttributeFuncs::typeIncompatible(ParamTy))) - return false; // Attribute not compatible with transformed value. - - if (Call.isInAllocaArgument(i)) - return false; // Cannot transform to and from inalloca. + if (Call.isInAllocaArgument(i) || + CallerPAL.hasParamAttr(i, Attribute::Preallocated)) + return false; // Cannot transform to and from inalloca/preallocated. if (CallerPAL.hasParamAttr(i, Attribute::SwiftError)) return false; @@ -3142,13 +3139,19 @@ NewArg = Builder.CreateBitOrPointerCast(*AI, ParamTy); Args.push_back(NewArg); - // Add any parameter attributes. + // Add any parameter attributes except the ones incompatible with the new + // type. if (CallerPAL.hasParamAttr(i, Attribute::ByVal)) { - AttrBuilder AB(FT->getContext(), CallerPAL.getParamAttrs(i)); + AttrBuilder AB( + FT->getContext(), + CallerPAL.getParamAttrs(i).removeAttributes( + FT->getContext(), AttributeFuncs::typeIncompatible(ParamTy))); AB.addByValAttr(NewArg->getType()->getPointerElementType()); ArgAttrs.push_back(AttributeSet::get(Ctx, AB)); - } else - ArgAttrs.push_back(CallerPAL.getParamAttrs(i)); + } else { + ArgAttrs.push_back(CallerPAL.getParamAttrs(i).removeAttributes( + FT->getContext(), AttributeFuncs::typeIncompatible(ParamTy))); + } } // If the function takes more arguments than the call was taking, add them diff --git a/llvm/test/Transforms/InstCombine/call-cast-attrs.ll b/llvm/test/Transforms/InstCombine/call-cast-attrs.ll --- a/llvm/test/Transforms/InstCombine/call-cast-attrs.ll +++ b/llvm/test/Transforms/InstCombine/call-cast-attrs.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -passes=instcombine -S | FileCheck %s +; RUN: opt < %s -passes=instcombine -data-layout="p:32:32" -S | FileCheck %s --check-prefixes=CHECK,CHECK32 +; RUN: opt < %s -passes=instcombine -data-layout="p:64:64" -S | FileCheck %s --check-prefixes=CHECK,CHECK64 define signext i32 @b(i32* inreg %x) { ret i32 0 @@ -20,10 +21,17 @@ call void bitcast (void (...)* @c to void (i32*)*)(i32* %y) call void bitcast (void (...)* @c to void (i32*)*)(i32* sret(i32) %y) call void bitcast (void (i32, ...)* @d to void (i32, i32*)*)(i32 0, i32* sret(i32) %y) + call void bitcast (void (i32, ...)* @d to void (i32, i32*)*)(i32 0, i32* nocapture %y) + call void bitcast (void (i32, ...)* @d to void (i32*)*)(i32* nocapture noundef %y) ret void } ; CHECK-LABEL: define void @g(i32* %y) -; CHECK: call i32 bitcast (i32 (i32*)* @b to i32 (i32)*)(i32 zeroext 0) -; CHECK: call void (...) @c(i32* %y) -; CHECK: call void bitcast (void (...)* @c to void (i32*)*)(i32* sret(i32) %y) -; CHECK: call void bitcast (void (i32, ...)* @d to void (i32, i32*)*)(i32 0, i32* sret(i32) %y) +; CHECK32: %1 = call i32 @b(i32* null) +; CHECK64: call i32 bitcast (i32 (i32*)* @b to i32 (i32)*)(i32 zeroext 0) +; CHECK: call void (...) @c(i32* %y) +; CHECK: call void bitcast (void (...)* @c to void (i32*)*)(i32* sret(i32) %y) +; CHECK: call void bitcast (void (i32, ...)* @d to void (i32, i32*)*)(i32 0, i32* sret(i32) %y) +; CHECK: call void (i32, ...) @d(i32 0, i32* nocapture %y) +; CHECK32: %2 = ptrtoint i32* %y to i32 +; CHECK32: call void (i32, ...) @d(i32 noundef %2) +; CHECK64: call void bitcast (void (i32, ...)* @d to void (i32*)*)(i32* nocapture noundef %y)