Skip to content

Commit

Permalink
[InstCombine] shrink truncated insertelement into undef vector
Browse files Browse the repository at this point in the history
This is the 2nd part of solving:
http://lists.llvm.org/pipermail/llvm-dev/2017-February/110293.html

D30123 moves the trunc ahead of the shuffle, and this moves the trunc ahead of the insertelement. 
We're limiting this transform to undef rather than any constant to avoid backend problems.

Differential Revision: https://reviews.llvm.org/D30137


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297242 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
rotateright committed Mar 7, 2017
1 parent 35c6dd2 commit 70bc85f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
38 changes: 38 additions & 0 deletions lib/Transforms/InstCombine/InstCombineCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,38 @@ static Instruction *shrinkSplatShuffle(TruncInst &Trunc,
return nullptr;
}

/// Try to narrow the width of an insert element. This could be generalized for
/// any vector constant, but we limit the transform to insertion into undef to
/// avoid potential backend problems from unsupported insertion widths. This
/// could also be extended to handle the case of inserting a scalar constant
/// into a vector variable.
static Instruction *shrinkInsertElt(CastInst &Trunc,
InstCombiner::BuilderTy &Builder) {
Instruction::CastOps Opcode = Trunc.getOpcode();
assert((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) &&
"Unexpected instruction for shrinking");

auto *InsElt = dyn_cast<InsertElementInst>(Trunc.getOperand(0));
if (!InsElt || !InsElt->hasOneUse())
return nullptr;

Type *DestTy = Trunc.getType();
Type *DestScalarTy = DestTy->getScalarType();
Value *VecOp = InsElt->getOperand(0);
Value *ScalarOp = InsElt->getOperand(1);
Value *Index = InsElt->getOperand(2);

if (isa<UndefValue>(VecOp)) {
// trunc (inselt undef, X, Index) --> inselt undef, (trunc X), Index
// fptrunc (inselt undef, X, Index) --> inselt undef, (fptrunc X), Index
UndefValue *NarrowUndef = UndefValue::get(DestTy);
Value *NarrowOp = Builder.CreateCast(Opcode, ScalarOp, DestScalarTy);
return InsertElementInst::Create(NarrowUndef, NarrowOp, Index);
}

return nullptr;
}

Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
if (Instruction *Result = commonCastTransforms(CI))
return Result;
Expand Down Expand Up @@ -574,6 +606,9 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
if (Instruction *I = shrinkSplatShuffle(CI, *Builder))
return I;

if (Instruction *I = shrinkInsertElt(CI, *Builder))
return I;

if (Src->hasOneUse() && isa<IntegerType>(SrcTy) &&
shouldChangeType(SrcTy, DestTy)) {
// Transform "trunc (shl X, cst)" -> "shl (trunc X), cst" so long as the
Expand Down Expand Up @@ -1426,6 +1461,9 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) {
}
}

if (Instruction *I = shrinkInsertElt(CI, *Builder))
return I;

return nullptr;
}

Expand Down
32 changes: 32 additions & 0 deletions test/Transforms/InstCombine/vector-casts.ll
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,35 @@ define <8 x i32> @pr24458(<8 x float> %n) {
ret <8 x i32> %wrong
}

; Hoist a trunc to a scalar if we're inserting into an undef vector.
; trunc (inselt undef, X, Index) --> inselt undef, (trunc X), Index

define <3 x i16> @trunc_inselt_undef(i32 %x) {
; CHECK-LABEL: @trunc_inselt_undef(
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 %x to i16
; CHECK-NEXT: [[TRUNC:%.*]] = insertelement <3 x i16> undef, i16 [[TMP1]], i32 1
; CHECK-NEXT: ret <3 x i16> [[TRUNC]]
;
%vec = insertelement <3 x i32> undef, i32 %x, i32 1
%trunc = trunc <3 x i32> %vec to <3 x i16>
ret <3 x i16> %trunc
}

; Hoist a trunc to a scalar if we're inserting into an undef vector.
; trunc (inselt undef, X, Index) --> inselt undef, (trunc X), Index

define <2 x float> @fptrunc_inselt_undef(double %x, i32 %index) {
; CHECK-LABEL: @fptrunc_inselt_undef(
; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double %x to float
; CHECK-NEXT: [[TRUNC:%.*]] = insertelement <2 x float> undef, float [[TMP1]], i32 %index
; CHECK-NEXT: ret <2 x float> [[TRUNC]]
;
%vec = insertelement <2 x double> <double undef, double undef>, double %x, i32 %index
%trunc = fptrunc <2 x double> %vec to <2 x float>
ret <2 x float> %trunc
}

; TODO: Strengthen the backend, so we can have this canonicalization.
; Insert a scalar int into a constant vector and truncate:
; trunc (inselt C, X, Index) --> inselt C, (trunc X), Index

Expand All @@ -230,6 +259,7 @@ define <3 x i16> @trunc_inselt1(i32 %x) {
ret <3 x i16> %trunc
}

; TODO: Strengthen the backend, so we can have this canonicalization.
; Insert a scalar FP into a constant vector and FP truncate:
; fptrunc (inselt C, X, Index) --> inselt C, (fptrunc X), Index

Expand All @@ -244,6 +274,7 @@ define <2 x float> @fptrunc_inselt1(double %x, i32 %index) {
ret <2 x float> %trunc
}

; TODO: Strengthen the backend, so we can have this canonicalization.
; Insert a scalar int constant into a vector and truncate:
; trunc (inselt X, C, Index) --> inselt (trunc X), C', Index

Expand All @@ -258,6 +289,7 @@ define <8 x i16> @trunc_inselt2(<8 x i32> %x, i32 %index) {
ret <8 x i16> %trunc
}

; TODO: Strengthen the backend, so we can have this canonicalization.
; Insert a scalar FP constant into a vector and FP truncate:
; fptrunc (inselt X, C, Index) --> inselt (fptrunc X), C', Index

Expand Down

0 comments on commit 70bc85f

Please sign in to comment.