OSDN Git Service

[InstCombine] refactor trunc(binop) transforms; NFCI
authorSanjay Patel <spatel@rotateright.com>
Sat, 5 Aug 2017 15:19:18 +0000 (15:19 +0000)
committerSanjay Patel <spatel@rotateright.com>
Sat, 5 Aug 2017 15:19:18 +0000 (15:19 +0000)
In addition to moving the shift transforms over, we may want to
detect too-wide rotate patterns here (PR34046).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310181 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCasts.cpp
lib/Transforms/InstCombine/InstCombineInternal.h

index 566a143..3139cb3 100644 (file)
@@ -443,24 +443,49 @@ static Instruction *foldVecTruncToExtElt(TruncInst &Trunc, InstCombiner &IC) {
   return ExtractElementInst::Create(VecInput, IC.Builder.getInt32(Elt));
 }
 
-/// Try to narrow the width of bitwise logic instructions with constants.
-Instruction *InstCombiner::shrinkBitwiseLogic(TruncInst &Trunc) {
+/// Try to narrow the width of math or bitwise logic instructions by pulling a
+/// truncate ahead of binary operators.
+/// TODO: Transforms for truncated shifts should be moved into here.
+Instruction *InstCombiner::narrowBinOp(TruncInst &Trunc) {
   Type *SrcTy = Trunc.getSrcTy();
   Type *DestTy = Trunc.getType();
   if (isa<IntegerType>(SrcTy) && !shouldChangeType(SrcTy, DestTy))
     return nullptr;
 
-  BinaryOperator *LogicOp;
-  Constant *C;
-  if (!match(Trunc.getOperand(0), m_OneUse(m_BinOp(LogicOp))) ||
-      !LogicOp->isBitwiseLogicOp() ||
-      !match(LogicOp->getOperand(1), m_Constant(C)))
+  BinaryOperator *BinOp;
+  if (!match(Trunc.getOperand(0), m_OneUse(m_BinOp(BinOp))))
     return nullptr;
 
-  // trunc (logic X, C) --> logic (trunc X, C')
-  Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy);
-  Value *NarrowOp0 = Builder.CreateTrunc(LogicOp->getOperand(0), DestTy);
-  return BinaryOperator::Create(LogicOp->getOpcode(), NarrowOp0, NarrowC);
+  switch (BinOp->getOpcode()) {
+  case Instruction::And:
+  case Instruction::Or:
+  case Instruction::Xor:
+  case Instruction::Add:
+  case Instruction::Mul: {
+    Constant *C;
+    if (match(BinOp->getOperand(1), m_Constant(C))) {
+      // trunc (binop X, C) --> binop (trunc X, C')
+      Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy);
+      Value *TruncX = Builder.CreateTrunc(BinOp->getOperand(0), DestTy);
+      return BinaryOperator::Create(BinOp->getOpcode(), TruncX, NarrowC);
+    }
+    break;
+  }
+  case Instruction::Sub: {
+    Constant *C;
+    if (match(BinOp->getOperand(0), m_Constant(C))) {
+      // trunc (binop C, X) --> binop (trunc C', X)
+      Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy);
+      Value *TruncX = Builder.CreateTrunc(BinOp->getOperand(1), DestTy);
+      return BinaryOperator::Create(BinOp->getOpcode(), NarrowC, TruncX);
+    }
+    break;
+  }
+
+  default: break;
+  }
+
+  return nullptr;
 }
 
 /// Try to narrow the width of a splat shuffle. This could be generalized to any
@@ -558,33 +583,6 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
     return new ICmpInst(ICmpInst::ICMP_NE, Src, Zero);
   }
 
-  if ((!isa<IntegerType>(SrcTy) || shouldChangeType(SrcTy, DestTy)) &&
-      Src->hasOneUse()) {
-    // Add/sub/mul can always be narrowed if we're killing the high bits.
-    // If one operand is a constant, then we're not generating more
-    // instructions to perform the narrower math op.
-    Value *X;
-    Constant *C;
-    if (match(Src, m_Add(m_Value(X), m_Constant(C)))) {
-      // trunc(add X, C) --> add(trunc X, C')
-      Value *TruncX = Builder.CreateTrunc(X, DestTy);
-      Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy);
-      return BinaryOperator::CreateAdd(TruncX, NarrowC);
-    }
-    if (match(Src, m_Mul(m_Value(X), m_Constant(C)))) {
-      // trunc(mul X, C) --> mul(trunc X, C')
-      Value *TruncX = Builder.CreateTrunc(X, DestTy);
-      Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy);
-      return BinaryOperator::CreateMul(TruncX, NarrowC);
-    }
-    if (match(Src, m_Sub(m_Constant(C), m_Value(X)))) {
-      // trunc(sub C, X) --> sub(C', trunc X)
-      Value *TruncX = Builder.CreateTrunc(X, DestTy);
-      Constant *NarrowC = ConstantExpr::getTrunc(C, DestTy);
-      return BinaryOperator::CreateSub(NarrowC, TruncX);
-    }
-  }
-
   // FIXME: Maybe combine the next two transforms to handle the no cast case
   // more efficiently. Support vector types. Cleanup code by using m_OneUse.
 
@@ -643,7 +641,7 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
     }
   }
 
-  if (Instruction *I = shrinkBitwiseLogic(CI))
+  if (Instruction *I = narrowBinOp(CI))
     return I;
 
   if (Instruction *I = shrinkSplatShuffle(CI, Builder))
index e3dfc66..f550dd5 100644 (file)
@@ -439,7 +439,7 @@ private:
   Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
   Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
   Instruction *foldCastedBitwiseLogic(BinaryOperator &I);
-  Instruction *shrinkBitwiseLogic(TruncInst &Trunc);
+  Instruction *narrowBinOp(TruncInst &Trunc);
   Instruction *optimizeBitCastFromPhi(CastInst &CI, PHINode *PN);
 
   /// Determine if a pair of casts can be replaced by a single cast.