diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 00b877b8a07ef..fe0f308223387 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -462,6 +462,13 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) { return ScalarPHI; } + // If SrcVec is a subvector starting at index 0, extract from the + // wider source vector + Value *V; + if (match(SrcVec, + m_Intrinsic(m_Value(V), m_Zero()))) + return ExtractElementInst::Create(V, Index); + // TODO come up with a n-ary matcher that subsumes both unary and // binary matchers. UnaryOperator *UO; diff --git a/llvm/test/Transforms/InstCombine/scalable-extract-subvec-elt.ll b/llvm/test/Transforms/InstCombine/scalable-extract-subvec-elt.ll new file mode 100644 index 0000000000000..1e089e1168f66 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/scalable-extract-subvec-elt.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -passes=instcombine < %s | FileCheck %s + +define i1 @extract_const_idx( %a) { +; CHECK-LABEL: define i1 @extract_const_idx( +; CHECK-SAME: [[A:%.*]]) { +; CHECK-NEXT: [[ELT:%.*]] = extractelement [[A]], i64 1 +; CHECK-NEXT: ret i1 [[ELT]] +; + %subvec = call @llvm.vector.extract.nxv2i1.nxv4i1.i64( %a, i64 0) + %elt = extractelement %subvec, i32 1 + ret i1 %elt +} + +define float @extract_variable_idx( %a, i32 %idx) { +; CHECK-LABEL: define float @extract_variable_idx( +; CHECK-SAME: [[A:%.*]], i32 [[IDX:%.*]]) { +; CHECK-NEXT: [[ELT:%.*]] = extractelement [[A]], i32 [[IDX]] +; CHECK-NEXT: ret float [[ELT]] +; + %subvec = call @llvm.vector.extract.nxv2f32.nxv4f32.i64( %a, i64 0) + %elt = extractelement %subvec, i32 %idx + ret float %elt +} + +define float @negative_test( %a) { +; CHECK-LABEL: define float @negative_test( +; CHECK-SAME: [[A:%.*]]) { +; CHECK-NEXT: [[SUBVEC:%.*]] = call @llvm.vector.extract.nxv2f32.nxv4f32( [[A]], i64 2) +; CHECK-NEXT: [[ELT:%.*]] = extractelement [[SUBVEC]], i64 1 +; CHECK-NEXT: ret float [[ELT]] +; + %subvec = call @llvm.vector.extract.nxv2f32.nxv4f32.i64( %a, i64 2) + %elt = extractelement %subvec, i32 1 + ret float %elt +}