diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -656,6 +656,16 @@ return cmpNumbers(RMWI->getSyncScopeID(), cast(R)->getSyncScopeID()); } + if (const ShuffleVectorInst *SVI = dyn_cast(L)) { + ArrayRef LMask = SVI->getShuffleMask(); + ArrayRef RMask = cast(R)->getShuffleMask(); + if (int Res = cmpNumbers(LMask.size(), RMask.size())) + return Res; + for (size_t i = 0, e = LMask.size(); i != e; ++i) { + if (int Res = cmpNumbers(LMask[i], RMask[i])) + return Res; + } + } if (const PHINode *PNL = dyn_cast(L)) { const PHINode *PNR = cast(R); // Ensure that in addition to the incoming values being identical diff --git a/llvm/test/Transforms/MergeFunc/shufflevector.ll b/llvm/test/Transforms/MergeFunc/shufflevector.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/MergeFunc/shufflevector.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -mergefunc < %s | FileCheck %s + +define internal <2 x i32> @test1(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[X:%.*]] = shufflevector <2 x i32> [[V1:%.*]], <2 x i32> [[V2:%.*]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[X]] +; + %x = shufflevector <2 x i32> %v1, <2 x i32> %v2, <2 x i32> + ret <2 x i32> %x +} + +; Same mask as test1. +define internal <2 x i32> @test2(<2 x i32> %v1, <2 x i32> %v2) { + %x = shufflevector <2 x i32> %v1, <2 x i32> %v2, <2 x i32> + ret <2 x i32> %x +} + +; Different mask than test1, don't merge. +define internal <2 x i32> @test3(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[X:%.*]] = shufflevector <2 x i32> [[V1:%.*]], <2 x i32> [[V2:%.*]], <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[X]] +; + %x = shufflevector <2 x i32> %v1, <2 x i32> %v2, <2 x i32> + ret <2 x i32> %x +} + +define void @caller(<2 x i32> %v1, <2 x i32> %v2) { +; CHECK-LABEL: @caller( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @test1(<2 x i32> [[V1:%.*]], <2 x i32> [[V2:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @test1(<2 x i32> [[V1]], <2 x i32> [[V2]]) +; CHECK-NEXT: [[TMP3:%.*]] = call <2 x i32> @test3(<2 x i32> [[V1]], <2 x i32> [[V2]]) +; CHECK-NEXT: ret void +; + call <2 x i32> @test1(<2 x i32> %v1, <2 x i32> %v2) + call <2 x i32> @test2(<2 x i32> %v1, <2 x i32> %v2) + call <2 x i32> @test3(<2 x i32> %v1, <2 x i32> %v2) + ret void +}