diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -47,6 +47,11 @@ if (CV->isAllOnesValue()) return Constant::getAllOnesValue(DstTy); if (CV->isNullValue()) return Constant::getNullValue(DstTy); + // Do not iterate on scalable vector. The num of elements is unknown at + // compile-time. + if (DstTy->isScalable()) + return nullptr; + // If this cast changes element count then we can't handle it here: // doing so requires endianness information. This should be handled by // Analysis/ConstantFolding.cpp @@ -563,6 +568,29 @@ if (isAllNull) // This is casting one pointer type to another, always BitCast return ConstantExpr::getPointerCast(CE->getOperand(0), DestTy); + } else if (CE->getType()->isVectorTy() && DestTy->isVectorTy() && + CE->getType()->getVectorElementCount() == + DestTy->getVectorElementCount() && + CE->getOpcode() == Instruction::ShuffleVector && + opc == Instruction::BitCast) { + // For splat vector, fold bitcast to splat value. + // BitCast(ShuffleVector(InsertElement(C1, SplatV, Zero), C2, Zero)) to NewType + // into + // ShuffleVector(InsertElement(C1, BitCast(SplatV) to NewType, Zero), C2, Zero) + Constant *SplatV, *C1, *C2, *ZeroIdx, *ZeroMask; + if (match(CE, m_ShuffleVector( + m_InsertElement( + m_Constant(C1), m_Constant(SplatV), + m_CombineAnd(m_Zero(), m_Constant(ZeroIdx))), + m_Constant(C2), + m_CombineAnd(m_Zero(), m_Constant(ZeroMask))))) { + auto *CastedSplatV = + ConstantExpr::getCast(opc, SplatV, DestTy->getScalarType()); + return ConstantExpr::getShuffleVector( + ConstantExpr::getInsertElement( + ConstantExpr::getCast(opc, C1, DestTy), CastedSplatV, ZeroIdx), + ConstantExpr::getCast(opc, C2, DestTy), ZeroMask); + } } } diff --git a/llvm/test/Analysis/ConstantFolding/bitcast.ll b/llvm/test/Analysis/ConstantFolding/bitcast.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/ConstantFolding/bitcast.ll @@ -0,0 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -constprop -S -verify | FileCheck %s + +define @bitcast_scalable_constant() { +; CHECK-LABEL: @bitcast_scalable_constant( +; CHECK-NEXT: ret shufflevector ( insertelement ( undef, float 0x36A0000000000000, i32 0), undef, zeroinitializer) +; + %i1 = insertelement undef, i32 1, i32 0 + %i2 = shufflevector %i1, undef, zeroinitializer + %i3 = bitcast %i2 to + ret %i3 +}