From 82fdab335881cd90f8f7ab3ad1f1ca0bb3ee886a Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Tue, 21 Dec 2010 14:00:22 +0000 Subject: [PATCH] Pull a few more simplifications out of instcombine (there are still plenty left though!), in particular for multiplication. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122330 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/InstructionSimplify.h | 5 + lib/Analysis/InstructionSimplify.cpp | 91 ++++++++++++++++++- .../InstCombine/InstCombineMulDivRem.cpp | 9 +- 3 files changed, 94 insertions(+), 11 deletions(-) diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 4d41cb580b8..c2812dfd25a 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -39,6 +39,11 @@ namespace llvm { Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0, const DominatorTree *DT = 0); + /// SimplifyMulInst - Given operands for a Mul, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + /// SimplifyOrInst - Given operands for an Or, see if we can /// fold the result. If not, this returns null. Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0, diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index c85e2293f00..df9449716c0 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -28,10 +28,16 @@ using namespace llvm::PatternMatch; #define RecursionLimit 3 +static Value *SimplifyAndInst(Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); static Value *SimplifyBinOp(unsigned, Value *, Value *, const TargetData *, const DominatorTree *, unsigned); static Value *SimplifyCmpInst(unsigned, Value *, Value *, const TargetData *, const DominatorTree *, unsigned); +static Value *SimplifyOrInst(Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); +static Value *SimplifyXorInst(Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); /// ValueDominatesPHI - Does the given value dominate the specified phi node? static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) { @@ -125,8 +131,8 @@ static Value *FactorizeBinOp(unsigned Opcode, Value *LHS, Value *RHS, return 0; // The expression has the form "(A op' B) op (C op' D)". - Value *A = Op0->getOperand(0); Value *B = Op0->getOperand(1); - Value *C = Op1->getOperand(0); Value *D = Op1->getOperand(1); + Value *A = Op0->getOperand(0), *B = Op0->getOperand(1); + Value *C = Op1->getOperand(0), *D = Op1->getOperand(1); // Use left distributivity, i.e. "X op' (Y op Z) = (X op' Y) op (X op' Z)". // Does the instruction have the form "(A op' B) op (A op' D)" or, in the @@ -484,6 +490,10 @@ static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, match(Op1, m_Not(m_Specific(Op0)))) return Constant::getAllOnesValue(Op0->getType()); + /// i1 add -> xor. + if (!MaxRecurse && Op0->getType()->isIntegerTy(1)) + return SimplifyXorInst(Op0, Op1, TD, DT, MaxRecurse-1); + // Try some generic simplifications for associative operations. if (Value *V = SimplifyAssociativeBinOp(Instruction::Add, Op0, Op1, TD, DT, MaxRecurse)) @@ -543,6 +553,10 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, match(Op0, m_Add(m_Specific(Op1), m_Value(X)))) return X; + /// i1 sub -> xor. + if (!MaxRecurse && Op0->getType()->isIntegerTy(1)) + return SimplifyXorInst(Op0, Op1, TD, DT, MaxRecurse-1); + // Mul distributes over Sub. Try some generic simplifications based on this. if (Value *V = FactorizeBinOp(Instruction::Sub, Op0, Op1, Instruction::Mul, TD, DT, MaxRecurse)) @@ -565,6 +579,69 @@ Value *llvm::SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, return ::SimplifySubInst(Op0, Op1, isNSW, isNUW, TD, DT, RecursionLimit); } +/// SimplifyMulInst - Given operands for a Mul, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Mul, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // X * undef -> 0 + if (isa(Op1)) + return Constant::getNullValue(Op0->getType()); + + // X * 0 -> 0 + if (match(Op1, m_Zero())) + return Op1; + + // X * 1 -> X + if (match(Op1, m_One())) + return Op0; + + /// i1 mul -> and. + if (!MaxRecurse && Op0->getType()->isIntegerTy(1)) + return SimplifyAndInst(Op0, Op1, TD, DT, MaxRecurse-1); + + // Try some generic simplifications for associative operations. + if (Value *V = SimplifyAssociativeBinOp(Instruction::Mul, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // Mul distributes over Add. Try some generic simplifications based on this. + if (Value *V = ExpandBinOp(Instruction::Mul, Op0, Op1, Instruction::Add, + TD, DT, MaxRecurse)) + return V; + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverSelect(Instruction::Mul, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverPHI(Instruction::Mul, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyMulInst(Op0, Op1, TD, DT, RecursionLimit); +} + /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD, @@ -1087,15 +1164,16 @@ static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const TargetData *TD, const DominatorTree *DT, unsigned MaxRecurse) { switch (Opcode) { - case Instruction::And: return SimplifyAndInst(LHS, RHS, TD, DT, MaxRecurse); - case Instruction::Or: return SimplifyOrInst(LHS, RHS, TD, DT, MaxRecurse); - case Instruction::Xor: return SimplifyXorInst(LHS, RHS, TD, DT, MaxRecurse); case Instruction::Add: return SimplifyAddInst(LHS, RHS, /* isNSW */ false, /* isNUW */ false, TD, DT, MaxRecurse); case Instruction::Sub: return SimplifySubInst(LHS, RHS, /* isNSW */ false, /* isNUW */ false, TD, DT, MaxRecurse); + case Instruction::Mul: return SimplifyMulInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::And: return SimplifyAndInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::Or: return SimplifyOrInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::Xor: return SimplifyXorInst(LHS, RHS, TD, DT, MaxRecurse); default: if (Constant *CLHS = dyn_cast(LHS)) if (Constant *CRHS = dyn_cast(RHS)) { @@ -1168,6 +1246,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD, cast(I)->hasNoUnsignedWrap(), TD, DT); break; + case Instruction::Mul: + Result = SimplifyMulInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; case Instruction::And: Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT); break; diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 6bce6a2ed1d..a2fe0cf659e 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -14,6 +14,7 @@ #include "InstCombine.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Support/PatternMatch.h" using namespace llvm; using namespace PatternMatch; @@ -50,8 +51,8 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { bool Changed = SimplifyAssociativeOrCommutative(I); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - if (isa(Op1)) // undef * X -> 0 - return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); + if (Value *V = SimplifyMulInst(Op0, Op1, TD)) + return ReplaceInstUsesWith(I, V); // Simplify mul instructions with a constant RHS. if (Constant *Op1C = dyn_cast(Op1)) { @@ -64,10 +65,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { return BinaryOperator::CreateMul(SI->getOperand(0), ConstantExpr::getShl(CI, ShOp)); - if (CI->isZero()) - return ReplaceInstUsesWith(I, Op1C); // X * 0 == 0 - if (CI->equalsInt(1)) // X * 1 == X - return ReplaceInstUsesWith(I, Op0); if (CI->isAllOnesValue()) // X * -1 == 0 - X return BinaryOperator::CreateNeg(Op0, I.getName());