diff --git a/llvm/lib/Transforms/Scalar/Scalarizer.cpp b/llvm/lib/Transforms/Scalar/Scalarizer.cpp index 772f4c6c35dde..03d069c9fcb36 100644 --- a/llvm/lib/Transforms/Scalar/Scalarizer.cpp +++ b/llvm/lib/Transforms/Scalar/Scalarizer.cpp @@ -1084,6 +1084,17 @@ bool ScalarizerVisitor::visitExtractValueInst(ExtractValueInst &EVI) { ValueVector Res; if (!isStructOfMatchingFixedVectors(OpTy)) return false; + if (CallInst *CI = dyn_cast(Op)) { + Function *F = CI->getCalledFunction(); + if (!F) + return false; + Intrinsic::ID ID = F->getIntrinsicID(); + if (ID == Intrinsic::not_intrinsic || !isTriviallyScalarizable(ID)) + return false; + // Note: Fall through means Operand is a`CallInst` and it is defined in + // `isTriviallyScalarizable`. + } else + return false; Type *VecType = cast(OpTy->getContainedType(0)); std::optional VS = getVectorSplit(VecType); if (!VS) diff --git a/llvm/test/Transforms/Scalarizer/uadd_overflow.ll b/llvm/test/Transforms/Scalarizer/uadd_overflow.ll new file mode 100644 index 0000000000000..39094451523a5 --- /dev/null +++ b/llvm/test/Transforms/Scalarizer/uadd_overflow.ll @@ -0,0 +1,16 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt %s -passes='function(scalarizer)' -S | FileCheck %s + +; Test to make sure that struct return intrinsics that are not `isTriviallyScalarizable` do not get scalarized. + +define <3 x i32> @test_(<3 x i32> %a, <3 x i32> %b) { +; CHECK-LABEL: define <3 x i32> @test_( +; CHECK-SAME: <3 x i32> [[A:%.*]], <3 x i32> [[B:%.*]]) { +; CHECK-NEXT: [[R:%.*]] = call { <3 x i32>, <3 x i1> } @llvm.uadd.with.overflow.v3i32(<3 x i32> [[B]], <3 x i32> [[B]]) +; CHECK-NEXT: [[EL:%.*]] = extractvalue { <3 x i32>, <3 x i1> } [[R]], 0 +; CHECK-NEXT: ret <3 x i32> [[EL]] +; + %r = call { <3 x i32>, <3 x i1> } @llvm.uadd.with.overflow.v3i32(<3 x i32> %b, <3 x i32> %b) + %el = extractvalue { <3 x i32>, <3 x i1> } %r, 0 + ret <3 x i32> %el +}