diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -218,9 +218,29 @@ LLVM_DEBUG(dbgs() << "ARG PROMOTION: Promoting to:" << *NF << "\n" << "From: " << *F); + uint64_t LargestVectorWidth = 0; + for (auto *I : Params) + if (auto *VT = dyn_cast(I)) + LargestVectorWidth = std::max( + LargestVectorWidth, VT->getPrimitiveSizeInBits().getKnownMinSize()); + + auto UpdateMLVW = [LargestVectorWidth, F](const AttributeList &PAL, + AttributeList &NewPAL) { + Attribute MLVW = PAL.getFnAttr("min-legal-vector-width"); + if (MLVW.isValid()) { + uint64_t OldWidth; + MLVW.getValueAsString().getAsInteger(0, OldWidth); + if (LargestVectorWidth > OldWidth) + NewPAL = PAL.addFnAttribute(F->getContext(), "min-legal-vector-width", + llvm::utostr(LargestVectorWidth)); + } + }; + AttributeList NewPAL; + UpdateMLVW(PAL, NewPAL); + // Recompute the parameter attributes list based on the new arguments for // the function. - NF->setAttributes(AttributeList::get(F->getContext(), PAL.getFnAttrs(), + NF->setAttributes(AttributeList::get(F->getContext(), NewPAL.getFnAttrs(), PAL.getRetAttrs(), ArgAttrVec)); ArgAttrVec.clear(); @@ -305,9 +325,10 @@ NewCall->setTailCallKind(cast(&CB)->getTailCallKind()); NewCS = NewCall; } + UpdateMLVW(CallPAL, NewPAL); NewCS->setCallingConv(CB.getCallingConv()); NewCS->setAttributes(AttributeList::get(F->getContext(), - CallPAL.getFnAttrs(), + NewPAL.getFnAttrs(), CallPAL.getRetAttrs(), ArgAttrVec)); NewCS->copyMetadata(CB, {LLVMContext::MD_prof, LLVMContext::MD_dbg}); Args.clear(); diff --git a/llvm/test/Transforms/ArgumentPromotion/byval-3.ll b/llvm/test/Transforms/ArgumentPromotion/byval-3.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/ArgumentPromotion/byval-3.ll @@ -0,0 +1,25 @@ +; RUN: opt < %s -passes=argpromotion -S | FileCheck %s + +; CHECK-LABEL: define i32 @foo() #0 { +; CHECK-NEXT: %.val = load <32 x half>, <32 x half>* undef, align 4 +; CHECK-NEXT: call void @bar(<32 x half> %.val) #1 +; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: } + +; CHECK-LABEL: define internal void @bar(<32 x half> %.0.val) #1 { +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +; CHECK: attributes #1 = { uwtable "min-legal-vector-width"="512" } + +define i32 @foo() #0 { + call void @bar(<32 x half>* undef) + ret i32 0 +} + +define internal void @bar(<32 x half>*) #0 { + %2 = load <32 x half>, <32 x half>* %0, align 4 + ret void +} + +attributes #0 = { uwtable "min-legal-vector-width"="0" }