diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp --- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp +++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp @@ -3845,11 +3845,22 @@ // If we get here, we know the target features match. If one function // considers 512-bit vectors legal and the other does not, consider them // incompatible. - // FIXME Look at the arguments and only consider 512 bit or larger vectors? const TargetMachine &TM = getTLI()->getTargetMachine(); - return TM.getSubtarget(*Caller).useAVX512Regs() == - TM.getSubtarget(*Callee).useAVX512Regs(); + if (TM.getSubtarget(*Caller).useAVX512Regs() == + TM.getSubtarget(*Callee).useAVX512Regs()) + return true; + + // Consider the arguments compatible if they aren't vectors or aggregates. + // FIXME: Look at the size of vectors. + // FIXME: Look at the element types of aggregates to see if there are vectors. + // FIXME: The API of this function seems intended to allow arguments + // to be removed from the set, but the caller doesn't check if the set + // becomes empty so that may not work in practice. + return llvm::none_of(Args, [](Argument *A) { + auto *EltTy = cast(A->getType())->getElementType(); + return EltTy->isVectorTy() || EltTy->isAggregateType(); + }); } X86TTIImpl::TTI::MemCmpExpansionOptions diff --git a/llvm/test/Transforms/ArgumentPromotion/X86/min-legal-vector-width.ll b/llvm/test/Transforms/ArgumentPromotion/X86/min-legal-vector-width.ll --- a/llvm/test/Transforms/ArgumentPromotion/X86/min-legal-vector-width.ll +++ b/llvm/test/Transforms/ArgumentPromotion/X86/min-legal-vector-width.ll @@ -318,6 +318,64 @@ ret void } +; If the arguments are scalar, its ok to promote. +define internal i32 @scalar_callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(i32* %X, i32* %Y) #2 { +; CHECK-LABEL: define {{[^@]+}}@scalar_callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; CHECK-SAME: (i32 [[X_VAL:%.*]], i32 [[Y_VAL:%.*]]) +; CHECK-NEXT: [[C:%.*]] = add i32 [[X_VAL]], [[Y_VAL]] +; CHECK-NEXT: ret i32 [[C]] +; + %A = load i32, i32* %X + %B = load i32, i32* %Y + %C = add i32 %A, %B + ret i32 %C +} + +define i32 @scalar_avx512_legal256_prefer256_call_avx512_legal512_prefer256(i32* %B) #2 { +; CHECK-LABEL: define {{[^@]+}}@scalar_avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; CHECK-SAME: (i32* [[B:%.*]]) +; CHECK-NEXT: [[A:%.*]] = alloca i32 +; CHECK-NEXT: store i32 1, i32* [[A]] +; CHECK-NEXT: [[A_VAL:%.*]] = load i32, i32* [[A]] +; CHECK-NEXT: [[B_VAL:%.*]] = load i32, i32* [[B]] +; CHECK-NEXT: [[C:%.*]] = call i32 @scalar_callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(i32 [[A_VAL]], i32 [[B_VAL]]) +; CHECK-NEXT: ret i32 [[C]] +; + %A = alloca i32 + store i32 1, i32* %A + %C = call i32 @scalar_callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(i32* %A, i32* %B) + ret i32 %C +} + +; If the arguments are scalar, its ok to promote. +define internal i32 @scalar_callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(i32* %X, i32* %Y) #2 { +; CHECK-LABEL: define {{[^@]+}}@scalar_callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; CHECK-SAME: (i32 [[X_VAL:%.*]], i32 [[Y_VAL:%.*]]) +; CHECK-NEXT: [[C:%.*]] = add i32 [[X_VAL]], [[Y_VAL]] +; CHECK-NEXT: ret i32 [[C]] +; + %A = load i32, i32* %X + %B = load i32, i32* %Y + %C = add i32 %A, %B + ret i32 %C +} + +define i32 @scalar_avx512_legal512_prefer256_call_avx512_legal256_prefer256(i32* %B) #2 { +; CHECK-LABEL: define {{[^@]+}}@scalar_avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; CHECK-SAME: (i32* [[B:%.*]]) +; CHECK-NEXT: [[A:%.*]] = alloca i32 +; CHECK-NEXT: store i32 1, i32* [[A]] +; CHECK-NEXT: [[A_VAL:%.*]] = load i32, i32* [[A]] +; CHECK-NEXT: [[B_VAL:%.*]] = load i32, i32* [[B]] +; CHECK-NEXT: [[C:%.*]] = call i32 @scalar_callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(i32 [[A_VAL]], i32 [[B_VAL]]) +; CHECK-NEXT: ret i32 [[C]] +; + %A = alloca i32 + store i32 1, i32* %A + %C = call i32 @scalar_callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(i32* %A, i32* %B) + ret i32 %C +} + ; Function Attrs: argmemonly nounwind declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #5