diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -191,8 +191,7 @@ // If we are casting an integer to vector and extracting a portion, that is // a shift-right and truncate. - // TODO: Allow FP dest type by casting the trunc to FP? - if (X->getType()->isIntegerTy() && DestTy->isIntegerTy() && + if (X->getType()->isIntegerTy() && isDesirableIntType(X->getType()->getPrimitiveSizeInBits())) { assert(isa(Ext.getVectorOperand()->getType()) && "Expected fixed vector type for bitcast from scalar integer"); @@ -205,6 +204,12 @@ unsigned ShiftAmountC = ExtIndexC * DestTy->getPrimitiveSizeInBits(); if (!ShiftAmountC || Ext.getVectorOperand()->hasOneUse()) { Value *Lshr = Builder.CreateLShr(X, ShiftAmountC, "extelt.offset"); + if (DestTy->isFloatingPointTy()) { + Type *DstIntTy = IntegerType::getIntNTy( + Lshr->getContext(), DestTy->getPrimitiveSizeInBits()); + Value *Trunc = Builder.CreateTrunc(Lshr, DstIntTy); + return new BitCastInst(Trunc, DestTy); + } return new TruncInst(Lshr, DestTy); } } diff --git a/llvm/test/Transforms/InstCombine/extractelement.ll b/llvm/test/Transforms/InstCombine/extractelement.ll --- a/llvm/test/Transforms/InstCombine/extractelement.ll +++ b/llvm/test/Transforms/InstCombine/extractelement.ll @@ -407,19 +407,40 @@ ret i8 %r } -; negative test - can't have FP dest type without a cast - define half @bitcast_fpvec_index0(i32 %x) { -; ANY-LABEL: @bitcast_fpvec_index0( -; ANY-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <2 x half> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x half> [[V]], i64 0 -; ANY-NEXT: ret half [[R]] +; LE-LABEL: @bitcast_fpvec_index0( +; LE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; LE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE-NEXT: ret half [[R]] +; +; BE-LABEL: @bitcast_fpvec_index0( +; BE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; BE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; BE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE-NEXT: ret half [[R]] ; %v = bitcast i32 %x to <2 x half> %r = extractelement <2 x half> %v, i8 0 ret half %r } +define half @bitcast_fpvec_index1(i32 %x) { +; LE-LABEL: @bitcast_fpvec_index1( +; LE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; LE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; LE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE-NEXT: ret half [[R]] +; +; BE-LABEL: @bitcast_fpvec_index1( +; BE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; BE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE-NEXT: ret half [[R]] +; + %v = bitcast i32 %x to <2 x half> + %r = extractelement <2 x half> %v, i8 1 + ret half %r +} + ; negative test - need constant index define i8 @bitcast_scalar_index_variable(i32 %x, i64 %y) {