From 94da1de1cecf21cbcbc47972d5b780d7fdc7c63b Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sat, 5 Aug 2017 15:19:18 +0000 Subject: [PATCH] [InstCombine] refactor trunc(binop) transforms; NFCI In addition to moving the shift transforms over, we may want to detect too-wide rotate patterns here (PR34046). llvm-svn: 310181 --- .../InstCombine/InstCombineCasts.cpp | 76 +++++++++---------- .../InstCombine/InstCombineInternal.h | 2 +- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 566a143384d5..3139cb330455 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -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(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(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)) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index e3dfc66d1b80..f550dd539fd1 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -439,7 +439,7 @@ private: Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN); Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef 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.