From: Tim Northover Date: Wed, 5 Jun 2019 20:38:17 +0000 (+0000) Subject: InstCombine: correctly change byval type attribute alongside call args. X-Git-Tag: llvmorg-10-init~3671 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8d7f118ab2b9e51d6cf2811291e319b4d977eb8c;p=platform%2Fupstream%2Fllvm.git InstCombine: correctly change byval type attribute alongside call args. When the byval attribute has a type, it must match the pointee type of any parameter; but InstCombine was not updating the attribute when folding casts of various kinds away. llvm-svn: 362643 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 39aae2f..2c8fa20 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -4015,7 +4015,9 @@ static bool isSafeToEliminateVarargsCast(const CallBase &Call, Type* SrcTy = cast(CI->getOperand(0)->getType())->getElementType(); - Type* DstTy = cast(CI->getType())->getElementType(); + Type *DstTy = Call.isByValArgument(ix) + ? Call.getParamByValType(ix) + : cast(CI->getType())->getElementType(); if (!SrcTy->isSized() || !DstTy->isSized()) return false; if (DL.getTypeAllocSize(SrcTy) != DL.getTypeAllocSize(DstTy)) @@ -4223,6 +4225,15 @@ Instruction *InstCombiner::visitCallBase(CallBase &Call) { CastInst *CI = dyn_cast(*I); if (CI && isSafeToEliminateVarargsCast(Call, DL, CI, ix)) { *I = CI->getOperand(0); + + // Update the byval type to match the argument type. + if (Call.isByValArgument(ix)) { + Call.removeParamAttr(ix, Attribute::ByVal); + Call.addParamAttr( + ix, Attribute::getWithByValType( + Call.getContext(), + CI->getOperand(0)->getType()->getPointerElementType())); + } Changed = true; } } @@ -4353,7 +4364,7 @@ bool InstCombiner::transformConstExprCastCall(CallBase &Call) { if (!ParamPTy || !ParamPTy->getElementType()->isSized()) return false; - Type *CurElTy = ActTy->getPointerElementType(); + Type *CurElTy = Call.getParamByValType(i); if (DL.getTypeAllocSize(CurElTy) != DL.getTypeAllocSize(ParamPTy->getElementType())) return false; @@ -4407,6 +4418,7 @@ bool InstCombiner::transformConstExprCastCall(CallBase &Call) { // with the existing attributes. Wipe out any problematic attributes. RAttrs.remove(AttributeFuncs::typeIncompatible(NewRetTy)); + LLVMContext &Ctx = Call.getContext(); AI = Call.arg_begin(); for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) { Type *ParamTy = FT->getParamType(i); @@ -4417,7 +4429,12 @@ bool InstCombiner::transformConstExprCastCall(CallBase &Call) { Args.push_back(NewArg); // Add any parameter attributes. - ArgAttrs.push_back(CallerPAL.getParamAttributes(i)); + if (CallerPAL.hasParamAttribute(i, Attribute::ByVal)) { + AttrBuilder AB(CallerPAL.getParamAttributes(i)); + AB.addByValAttr(NewArg->getType()->getPointerElementType()); + ArgAttrs.push_back(AttributeSet::get(Ctx, AB)); + } else + ArgAttrs.push_back(CallerPAL.getParamAttributes(i)); } // If the function takes more arguments than the call was taking, add them @@ -4456,7 +4473,6 @@ bool InstCombiner::transformConstExprCastCall(CallBase &Call) { assert((ArgAttrs.size() == FT->getNumParams() || FT->isVarArg()) && "missing argument attributes"); - LLVMContext &Ctx = Callee->getContext(); AttributeList NewCallerPAL = AttributeList::get( Ctx, FnAttrs, AttributeSet::get(Ctx, RAttrs), ArgAttrs); diff --git a/llvm/test/Transforms/InstCombine/byval.ll b/llvm/test/Transforms/InstCombine/byval.ll new file mode 100644 index 0000000..2af32b8 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/byval.ll @@ -0,0 +1,24 @@ +; RUN: opt -S -instcombine %s | FileCheck %s + +declare void @add_byval_callee(double*) + +; CHECK-LABEL: define void @add_byval +; CHECK: [[ARG:%.*]] = bitcast i64* %in to double* +; CHECK: call void @add_byval_callee(double* byval(double) [[ARG]]) +define void @add_byval(i64* %in) { + %tmp = bitcast void (double*)* @add_byval_callee to void (i64*)* + call void %tmp(i64* byval(i64) %in) + ret void +} + +%t2 = type { i8 } + +; CHECK-LABEL: define void @vararg_byval +; CHECK: call void (i8, ...) @vararg_callee(i8 undef, i8* byval(i8) %p) +define void @vararg_byval(i8* %p) { + %tmp = bitcast i8* %p to %t2* + call void (i8, ...) @vararg_callee(i8 undef, %t2* byval(%t2) %tmp) + ret void +} + +declare void @vararg_callee(i8, ...)