Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -12100,6 +12100,7 @@ switch (II->getIntrinsicID()) { case Intrinsic::aarch64_neon_smull: case Intrinsic::aarch64_neon_umull: + case Intrinsic::aarch64_neon_pmull: if (areExtractShuffleVectors(II->getOperand(0), II->getOperand(1))) { Ops.push_back(&II->getOperandUse(0)); Ops.push_back(&II->getOperandUse(1)); Index: llvm/test/CodeGen/AArch64/neon-vmull-high-p8.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/neon-vmull-high-p8.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -verify-machineinstrs -mtriple=aarch64-linux-gnu -mattr=+neon | FileCheck %s + +; Check that pmull2 instruction is used for vmull_high_p8 intrinsic +; even if shufflevector instructions are located in different basic blocks, +; which can happen when vmull_high_p8 is used inside a loop body. +; + +define <8 x i16> @test_pmull2_sink(<16 x i8> %a, <16 x i8> %b, <8 x i16> %c, i1 %t) { +entry: +; CHECK-LABEL: test_pmull2_sink: +; CHECK: // %bb.1: +; CHECK-NEXT: pmull2 +; + %0 = shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> + br i1 %t, label %if.then, label %cleanup +if.then: + %1 = shufflevector <16 x i8> %b, <16 x i8> undef, <8 x i32> + %res = tail call <8 x i16> @llvm.aarch64.neon.pmull.v8i16(<8 x i8> %0, <8 x i8> %1) #0 + br label %cleanup +cleanup: + %retval = phi <8 x i16> [ %res, %if.then ], [ %c, %entry ] + ret <8 x i16> %retval +} + +declare <8 x i16> @llvm.aarch64.neon.pmull.v8i16(<8 x i8>, <8 x i8>) #0 +attributes #0 = { nofree noinline nounwind }