[llvm] r297242 - [InstCombine] shrink truncated insertelement into undef vector

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 7 15:27:14 PST 2017


Author: spatel
Date: Tue Mar  7 17:27:14 2017
New Revision: 297242

URL: http://llvm.org/viewvc/llvm-project?rev=297242&view=rev
Log:
[InstCombine] shrink truncated insertelement into undef vector

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

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
    llvm/trunk/test/Transforms/InstCombine/vector-casts.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp?rev=297242&r1=297241&r2=297242&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp Tue Mar  7 17:27:14 2017
@@ -480,6 +480,38 @@ static Instruction *shrinkSplatShuffle(T
   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;
@@ -574,6 +606,9 @@ Instruction *InstCombiner::visitTrunc(Tr
   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
@@ -1426,6 +1461,9 @@ Instruction *InstCombiner::visitFPTrunc(
     }
   }
 
+  if (Instruction *I = shrinkInsertElt(CI, *Builder))
+    return I;
+
   return nullptr;
 }
 

Modified: llvm/trunk/test/Transforms/InstCombine/vector-casts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/vector-casts.ll?rev=297242&r1=297241&r2=297242&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/vector-casts.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/vector-casts.ll Tue Mar  7 17:27:14 2017
@@ -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
 
@@ -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
 
@@ -244,6 +274,7 @@ define <2 x float> @fptrunc_inselt1(doub
   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
 
@@ -258,6 +289,7 @@ define <8 x i16> @trunc_inselt2(<8 x i32
   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
 




More information about the llvm-commits mailing list