diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -360,7 +360,7 @@ Constant *getElementValue(unsigned Idx) const; /// Return the number of elements in the array, vector, or struct. - unsigned getNumElements() const; + ElementCount getElementCount() const; /// Methods for support type inquiry through isa, cast, and dyn_cast: /// diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2876,13 +2876,14 @@ else if (auto GV = dyn_cast(&C)) EntryBuilder->buildGlobalValue(Reg, GV); else if (auto CAZ = dyn_cast(&C)) { - if (!CAZ->getType()->isVectorTy()) + if (!isa(CAZ->getType())) return false; // Return the scalar if it is a <1 x Ty> vector. - if (CAZ->getNumElements() == 1) + unsigned NumElts = CAZ->getElementCount().getFixedValue(); + if (NumElts == 1) return translateCopy(C, *CAZ->getElementValue(0u), *EntryBuilder.get()); SmallVector Ops; - for (unsigned i = 0; i < CAZ->getNumElements(); ++i) { + for (unsigned i = 0; i < NumElts; ++i) { Constant &Elt = *CAZ->getElementValue(i); Ops.push_back(getOrCreateVReg(Elt)); } diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -425,13 +425,15 @@ if (const auto *CC = dyn_cast(this)) return Elt < CC->getNumOperands() ? CC->getOperand(Elt) : nullptr; + if (const auto *CAZ = dyn_cast(this)) + return Elt < CAZ->getElementCount().getKnownMinValue() + ? CAZ->getElementValue(Elt) + : nullptr; + // FIXME: getNumElements() will fail for non-fixed vector types. if (isa(getType())) return nullptr; - if (const auto *CAZ = dyn_cast(this)) - return Elt < CAZ->getNumElements() ? CAZ->getElementValue(Elt) : nullptr; - if (const auto *PV = dyn_cast(this)) return Elt < PV->getNumElements() ? PV->getElementValue(Elt) : nullptr; @@ -1088,13 +1090,13 @@ return getStructElement(Idx); } -unsigned ConstantAggregateZero::getNumElements() const { +ElementCount ConstantAggregateZero::getElementCount() const { Type *Ty = getType(); if (auto *AT = dyn_cast(Ty)) - return AT->getNumElements(); + return ElementCount::getFixed(AT->getNumElements()); if (auto *VT = dyn_cast(Ty)) - return cast(VT)->getNumElements(); - return Ty->getStructNumElements(); + return cast(VT)->getElementCount(); + return ElementCount::getFixed(Ty->getStructNumElements()); } //===----------------------------------------------------------------------===// diff --git a/llvm/test/Transforms/InstCombine/scalable-select.ll b/llvm/test/Transforms/InstCombine/scalable-select.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/scalable-select.ll @@ -0,0 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -instcombine -S < %s | FileCheck %s + +; This test checks a regression in the select operand folding combine, in which +; Constant::getUniqueInteger would crash for a scalable-vector zeroinitializer. +define @select_opt( %b, %m) { +; CHECK-LABEL: @select_opt( +; CHECK-NEXT: [[C:%.*]] = add nsw [[B:%.*]], shufflevector ( insertelement ( undef, i32 2, i32 0), undef, zeroinitializer) +; CHECK-NEXT: [[D:%.*]] = select [[M:%.*]], [[C]], [[B]] +; CHECK-NEXT: ret [[D]] +; + %head = insertelement undef, i32 2, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %c = add nsw %b, %splat + %d = select %m, %c, %b + ret %d +}