mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 23:48:56 +00:00
Teach instsimplify some tricks about exact/nuw/nsw shifts.
improve interfaces to instsimplify to take this info. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125196 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6bfd77e315
commit
81a0dc9115
@ -57,17 +57,18 @@ namespace llvm {
|
||||
|
||||
/// SimplifyShlInst - Given operands for a Shl, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyLShrInst - Given operands for a LShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD = 0, const DominatorTree *DT=0);
|
||||
|
||||
/// SimplifyAShrInst - Given operands for a AShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD = 0,
|
||||
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||
|
@ -29,7 +29,7 @@
|
||||
using namespace llvm;
|
||||
using namespace llvm::PatternMatch;
|
||||
|
||||
#define RecursionLimit 3
|
||||
enum { RecursionLimit = 3 };
|
||||
|
||||
STATISTIC(NumExpand, "Number of expansions");
|
||||
STATISTIC(NumFactor , "Number of factorizations");
|
||||
@ -946,8 +946,9 @@ static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1,
|
||||
|
||||
/// SimplifyShlInst - Given operands for an Shl, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
static Value *SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT, unsigned MaxRecurse) {
|
||||
static Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||
const TargetData *TD, const DominatorTree *DT,
|
||||
unsigned MaxRecurse) {
|
||||
if (Value *V = SimplifyShift(Instruction::Shl, Op0, Op1, TD, DT, MaxRecurse))
|
||||
return V;
|
||||
|
||||
@ -955,18 +956,24 @@ static Value *SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
if (match(Op0, m_Undef()))
|
||||
return Constant::getNullValue(Op0->getType());
|
||||
|
||||
// (X >> A) << A -> X
|
||||
Value *X;
|
||||
if (match(Op0, m_Shr(m_Value(X), m_Specific(Op1))) &&
|
||||
cast<PossiblyExactOperator>(Op0)->isExact())
|
||||
return X;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT) {
|
||||
return ::SimplifyShlInst(Op0, Op1, TD, DT, RecursionLimit);
|
||||
Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||
const TargetData *TD, const DominatorTree *DT) {
|
||||
return ::SimplifyShlInst(Op0, Op1, isNSW, isNUW, TD, DT, RecursionLimit);
|
||||
}
|
||||
|
||||
/// SimplifyLShrInst - Given operands for an LShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
static Value *SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT, unsigned MaxRecurse) {
|
||||
static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD, const DominatorTree *DT,
|
||||
unsigned MaxRecurse) {
|
||||
if (Value *V = SimplifyShift(Instruction::LShr, Op0, Op1, TD, DT, MaxRecurse))
|
||||
return V;
|
||||
|
||||
@ -974,18 +981,25 @@ static Value *SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
if (match(Op0, m_Undef()))
|
||||
return Constant::getNullValue(Op0->getType());
|
||||
|
||||
// (X << A) >> A -> X
|
||||
Value *X;
|
||||
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
|
||||
cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap())
|
||||
return X;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT) {
|
||||
return ::SimplifyLShrInst(Op0, Op1, TD, DT, RecursionLimit);
|
||||
Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD, const DominatorTree *DT) {
|
||||
return ::SimplifyLShrInst(Op0, Op1, isExact, TD, DT, RecursionLimit);
|
||||
}
|
||||
|
||||
/// SimplifyAShrInst - Given operands for an AShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
static Value *SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT, unsigned MaxRecurse) {
|
||||
static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD, const DominatorTree *DT,
|
||||
unsigned MaxRecurse) {
|
||||
if (Value *V = SimplifyShift(Instruction::AShr, Op0, Op1, TD, DT, MaxRecurse))
|
||||
return V;
|
||||
|
||||
@ -997,12 +1011,18 @@ static Value *SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
if (match(Op0, m_Undef()))
|
||||
return Constant::getAllOnesValue(Op0->getType());
|
||||
|
||||
// (X << A) >> A -> X
|
||||
Value *X;
|
||||
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
|
||||
cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap())
|
||||
return X;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT) {
|
||||
return ::SimplifyAShrInst(Op0, Op1, TD, DT, RecursionLimit);
|
||||
Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD, const DominatorTree *DT) {
|
||||
return ::SimplifyAShrInst(Op0, Op1, isExact, TD, DT, RecursionLimit);
|
||||
}
|
||||
|
||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||
@ -1037,12 +1057,12 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
return Op0;
|
||||
|
||||
// A & ~A = ~A & A = 0
|
||||
Value *A = 0, *B = 0;
|
||||
if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
|
||||
(match(Op1, m_Not(m_Value(A))) && A == Op0))
|
||||
if (match(Op0, m_Not(m_Specific(Op1))) ||
|
||||
match(Op1, m_Not(m_Specific(Op0))))
|
||||
return Constant::getNullValue(Op0->getType());
|
||||
|
||||
// (A | ?) & A = A
|
||||
Value *A = 0, *B = 0;
|
||||
if (match(Op0, m_Or(m_Value(A), m_Value(B))) &&
|
||||
(A == Op1 || B == Op1))
|
||||
return Op1;
|
||||
@ -1126,12 +1146,12 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
return Op1;
|
||||
|
||||
// A | ~A = ~A | A = -1
|
||||
Value *A = 0, *B = 0;
|
||||
if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
|
||||
(match(Op1, m_Not(m_Value(A))) && A == Op0))
|
||||
if (match(Op0, m_Not(m_Specific(Op1))) ||
|
||||
match(Op1, m_Not(m_Specific(Op0))))
|
||||
return Constant::getAllOnesValue(Op0->getType());
|
||||
|
||||
// (A & ?) | A = A
|
||||
Value *A = 0, *B = 0;
|
||||
if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
|
||||
(A == Op1 || B == Op1))
|
||||
return Op1;
|
||||
@ -1206,9 +1226,8 @@ static Value *SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
return Constant::getNullValue(Op0->getType());
|
||||
|
||||
// A ^ ~A = ~A ^ A = -1
|
||||
Value *A = 0;
|
||||
if ((match(Op0, m_Not(m_Value(A))) && A == Op1) ||
|
||||
(match(Op1, m_Not(m_Value(A))) && A == Op0))
|
||||
if (match(Op0, m_Not(m_Specific(Op1))) ||
|
||||
match(Op1, m_Not(m_Specific(Op0))))
|
||||
return Constant::getAllOnesValue(Op0->getType());
|
||||
|
||||
// Try some generic simplifications for associative operations.
|
||||
@ -1794,21 +1813,25 @@ static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
||||
const TargetData *TD, const DominatorTree *DT,
|
||||
unsigned MaxRecurse) {
|
||||
switch (Opcode) {
|
||||
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::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::SDiv: return SimplifySDivInst(LHS, RHS, TD, DT, MaxRecurse);
|
||||
case Instruction::UDiv: return SimplifyUDivInst(LHS, RHS, TD, DT, MaxRecurse);
|
||||
case Instruction::FDiv: return SimplifyFDivInst(LHS, RHS, TD, DT, MaxRecurse);
|
||||
case Instruction::Shl: return SimplifyShlInst(LHS, RHS, TD, DT, MaxRecurse);
|
||||
case Instruction::LShr: return SimplifyLShrInst(LHS, RHS, TD, DT, MaxRecurse);
|
||||
case Instruction::AShr: return SimplifyAShrInst(LHS, RHS, TD, DT, MaxRecurse);
|
||||
case Instruction::Shl:
|
||||
return SimplifyShlInst(LHS, RHS, /*NSW*/false, /*NUW*/false,
|
||||
TD, DT, MaxRecurse);
|
||||
case Instruction::LShr:
|
||||
return SimplifyLShrInst(LHS, RHS, /*isexact*/ false, TD, DT, MaxRecurse);
|
||||
case Instruction::AShr:
|
||||
return SimplifyAShrInst(LHS, RHS, /*isexact*/false, 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::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))
|
||||
@ -1895,13 +1918,20 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
|
||||
Result = SimplifyFDivInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
case Instruction::Shl:
|
||||
Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1),
|
||||
cast<BinaryOperator>(I)->hasNoSignedWrap(),
|
||||
cast<BinaryOperator>(I)->hasNoUnsignedWrap(),
|
||||
TD, DT);
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
Result = SimplifyLShrInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
Result = SimplifyLShrInst(I->getOperand(0), I->getOperand(1),
|
||||
cast<BinaryOperator>(I)->isExact(),
|
||||
TD, DT);
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
Result = SimplifyAShrInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
Result = SimplifyAShrInst(I->getOperand(0), I->getOperand(1),
|
||||
cast<BinaryOperator>(I)->isExact(),
|
||||
TD, DT);
|
||||
break;
|
||||
case Instruction::And:
|
||||
Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
|
@ -617,13 +617,16 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitShl(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyShlInst(I.getOperand(0), I.getOperand(1), TD))
|
||||
if (Value *V = SimplifyShlInst(I.getOperand(0), I.getOperand(1),
|
||||
I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
|
||||
TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
return commonShiftTransforms(I);
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyLShrInst(I.getOperand(0), I.getOperand(1), TD))
|
||||
if (Value *V = SimplifyLShrInst(I.getOperand(0), I.getOperand(1),
|
||||
I.isExact(), TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
if (Instruction *R = commonShiftTransforms(I))
|
||||
@ -652,7 +655,8 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyAShrInst(I.getOperand(0), I.getOperand(1), TD))
|
||||
if (Value *V = SimplifyAShrInst(I.getOperand(0), I.getOperand(1),
|
||||
I.isExact(), TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
if (Instruction *R = commonShiftTransforms(I))
|
||||
|
44
test/Transforms/InstSimplify/exact-nsw-nuw.ll
Normal file
44
test/Transforms/InstSimplify/exact-nsw-nuw.ll
Normal file
@ -0,0 +1,44 @@
|
||||
; RUN: opt < %s -instsimplify -S | FileCheck %s
|
||||
|
||||
; PR8862
|
||||
|
||||
; CHECK: @shift1
|
||||
; CHECK: ret i32 %A
|
||||
define i32 @shift1(i32 %A, i32 %B) {
|
||||
%C = lshr exact i32 %A, %B
|
||||
%D = shl nuw i32 %C, %B
|
||||
ret i32 %D
|
||||
}
|
||||
|
||||
; CHECK: @shift2
|
||||
; CHECK: lshr
|
||||
; CHECK: ret i32 %D
|
||||
define i32 @shift2(i32 %A, i32 %B) {
|
||||
%C = lshr i32 %A, %B
|
||||
%D = shl nuw i32 %C, %B
|
||||
ret i32 %D
|
||||
}
|
||||
|
||||
; CHECK: @shift3
|
||||
; CHECK: ret i32 %A
|
||||
define i32 @shift3(i32 %A, i32 %B) {
|
||||
%C = ashr exact i32 %A, %B
|
||||
%D = shl nuw i32 %C, %B
|
||||
ret i32 %D
|
||||
}
|
||||
|
||||
; CHECK: @shift4
|
||||
; CHECK: ret i32 %A
|
||||
define i32 @shift4(i32 %A, i32 %B) {
|
||||
%C = shl nuw i32 %A, %B
|
||||
%D = lshr i32 %C, %B
|
||||
ret i32 %D
|
||||
}
|
||||
|
||||
; CHECK: @shift5
|
||||
; CHECK: ret i32 %A
|
||||
define i32 @shift5(i32 %A, i32 %B) {
|
||||
%C = shl nsw i32 %A, %B
|
||||
%D = ashr i32 %C, %B
|
||||
ret i32 %D
|
||||
}
|
Loading…
Reference in New Issue
Block a user