mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
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
This commit is contained in:
parent
9bd2c2e63c
commit
82fdab3358
@ -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,
|
||||
|
@ -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<Constant>(Op0)) {
|
||||
if (Constant *CRHS = dyn_cast<Constant>(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<UndefValue>(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<SelectInst>(Op0) || isa<SelectInst>(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<PHINode>(Op0) || isa<PHINode>(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<Constant>(LHS))
|
||||
if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
|
||||
@ -1168,6 +1246,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
|
||||
cast<BinaryOperator>(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;
|
||||
|
@ -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<UndefValue>(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<Constant>(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());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user