mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 05:00:26 +00:00
Move some shift transforms out of instcombine and into InstructionSimplify.
While there, I noticed that the transform "undef >>a X -> undef" was wrong. For example if X is 2 then the top two bits must be equal, so the result can not be anything. I fixed this in the constant folder as well. Also, I made the transform for "X << undef" stronger: it now folds to undef always, even though X might be zero. This is in accordance with the LangRef, but I must admit that it is fairly aggressive. Also, I added "i32 X << 32 -> undef" following the LangRef and the constant folder, likewise fairly aggressive. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123417 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
68a659d423
commit
c43cee3fbb
@ -35,16 +35,31 @@ namespace llvm {
|
||||
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
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);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// 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,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAndInst(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,
|
||||
|
@ -684,6 +684,136 @@ Value *llvm::SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
return ::SimplifyMulInst(Op0, Op1, TD, DT, RecursionLimit);
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
if (Constant *C0 = dyn_cast<Constant>(Op0)) {
|
||||
if (Constant *C1 = dyn_cast<Constant>(Op1)) {
|
||||
Constant *Ops[] = { C0, C1 };
|
||||
return ConstantFoldInstOperands(Instruction::Shl, C0->getType(), Ops, 2,
|
||||
TD);
|
||||
}
|
||||
}
|
||||
|
||||
// 0 << X -> 0
|
||||
if (match(Op0, m_Zero()))
|
||||
return Op0;
|
||||
|
||||
// X << 0 -> X
|
||||
if (match(Op1, m_Zero()))
|
||||
return Op0;
|
||||
|
||||
// undef << X -> 0
|
||||
if (isa<UndefValue>(Op0))
|
||||
return Constant::getNullValue(Op0->getType());
|
||||
|
||||
// X << undef -> undef because it may shift by the bitwidth.
|
||||
if (isa<UndefValue>(Op1))
|
||||
return Op1;
|
||||
|
||||
// Shifting by the bitwidth or more is undefined.
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1))
|
||||
if (CI->getValue().getLimitedValue() >=
|
||||
Op0->getType()->getScalarSizeInBits())
|
||||
return UndefValue::get(Op0->getType());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT) {
|
||||
return ::SimplifyShlInst(Op0, Op1, 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) {
|
||||
if (Constant *C0 = dyn_cast<Constant>(Op0)) {
|
||||
if (Constant *C1 = dyn_cast<Constant>(Op1)) {
|
||||
Constant *Ops[] = { C0, C1 };
|
||||
return ConstantFoldInstOperands(Instruction::LShr, C0->getType(), Ops, 2,
|
||||
TD);
|
||||
}
|
||||
}
|
||||
|
||||
// 0 >> X -> 0
|
||||
if (match(Op0, m_Zero()))
|
||||
return Op0;
|
||||
|
||||
// undef >>l X -> 0
|
||||
if (isa<UndefValue>(Op0))
|
||||
return Constant::getNullValue(Op0->getType());
|
||||
|
||||
// X >> 0 -> X
|
||||
if (match(Op1, m_Zero()))
|
||||
return Op0;
|
||||
|
||||
// X >> undef -> undef because it may shift by the bitwidth.
|
||||
if (isa<UndefValue>(Op1))
|
||||
return Op1;
|
||||
|
||||
// Shifting by the bitwidth or more is undefined.
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1))
|
||||
if (CI->getValue().getLimitedValue() >=
|
||||
Op0->getType()->getScalarSizeInBits())
|
||||
return UndefValue::get(Op0->getType());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT) {
|
||||
return ::SimplifyLShrInst(Op0, Op1, 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) {
|
||||
if (Constant *C0 = dyn_cast<Constant>(Op0)) {
|
||||
if (Constant *C1 = dyn_cast<Constant>(Op1)) {
|
||||
Constant *Ops[] = { C0, C1 };
|
||||
return ConstantFoldInstOperands(Instruction::AShr, C0->getType(), Ops, 2,
|
||||
TD);
|
||||
}
|
||||
}
|
||||
|
||||
// 0 >> X -> 0
|
||||
if (match(Op0, m_Zero()))
|
||||
return Op0;
|
||||
|
||||
// all ones >>a X -> all ones
|
||||
if (match(Op0, m_AllOnes()))
|
||||
return Op0;
|
||||
|
||||
// undef >>a X -> all ones
|
||||
if (isa<UndefValue>(Op0))
|
||||
return Constant::getAllOnesValue(Op0->getType());
|
||||
|
||||
// X >> 0 -> X
|
||||
if (match(Op1, m_Zero()))
|
||||
return Op0;
|
||||
|
||||
// X >> undef -> undef because it may shift by the bitwidth.
|
||||
if (isa<UndefValue>(Op1))
|
||||
return Op1;
|
||||
|
||||
// Shifting by the bitwidth or more is undefined.
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1))
|
||||
if (CI->getValue().getLimitedValue() >=
|
||||
Op0->getType()->getScalarSizeInBits())
|
||||
return UndefValue::get(Op0->getType());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
const DominatorTree *DT) {
|
||||
return ::SimplifyAShrInst(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,
|
||||
@ -1267,6 +1397,9 @@ static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
||||
/* isNUW */ false, TD, DT,
|
||||
MaxRecurse);
|
||||
case Instruction::Mul: return SimplifyMulInst(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::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);
|
||||
@ -1345,6 +1478,15 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD,
|
||||
case Instruction::Mul:
|
||||
Result = SimplifyMulInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
case Instruction::Shl:
|
||||
Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
case Instruction::LShr:
|
||||
Result = SimplifyLShrInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
case Instruction::AShr:
|
||||
Result = SimplifyAShrInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
case Instruction::And:
|
||||
Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT);
|
||||
break;
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "InstCombine.h"
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Support/PatternMatch.h"
|
||||
using namespace llvm;
|
||||
using namespace PatternMatch;
|
||||
@ -21,25 +22,6 @@ Instruction *InstCombiner::commonShiftTransforms(BinaryOperator &I) {
|
||||
assert(I.getOperand(1)->getType() == I.getOperand(0)->getType());
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
// shl X, 0 == X and shr X, 0 == X
|
||||
// shl 0, X == 0 and shr 0, X == 0
|
||||
if (Op1 == Constant::getNullValue(Op1->getType()) ||
|
||||
Op0 == Constant::getNullValue(Op0->getType()))
|
||||
return ReplaceInstUsesWith(I, Op0);
|
||||
|
||||
if (isa<UndefValue>(Op0)) {
|
||||
if (I.getOpcode() == Instruction::AShr) // undef >>s X -> undef
|
||||
return ReplaceInstUsesWith(I, Op0);
|
||||
else // undef << X -> 0, undef >>u X -> 0
|
||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||
}
|
||||
if (isa<UndefValue>(Op1)) {
|
||||
if (I.getOpcode() == Instruction::AShr) // X >>s undef -> X
|
||||
return ReplaceInstUsesWith(I, Op0);
|
||||
else // X << undef, X >>u undef -> 0
|
||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||
}
|
||||
|
||||
// See if we can fold away this shift.
|
||||
if (SimplifyDemandedInstructionBits(I))
|
||||
return &I;
|
||||
@ -635,10 +617,15 @@ Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, ConstantInt *Op1,
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitShl(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyShlInst(I.getOperand(0), I.getOperand(1), TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
return commonShiftTransforms(I);
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyLShrInst(I.getOperand(0), I.getOperand(1), TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
if (Instruction *R = commonShiftTransforms(I))
|
||||
return R;
|
||||
|
||||
@ -665,17 +652,14 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitAShr(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyAShrInst(I.getOperand(0), I.getOperand(1), TD))
|
||||
return ReplaceInstUsesWith(I, V);
|
||||
|
||||
if (Instruction *R = commonShiftTransforms(I))
|
||||
return R;
|
||||
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
if (ConstantInt *CSI = dyn_cast<ConstantInt>(Op0)) {
|
||||
// ashr int -1, X = -1 (for any arithmetic shift rights of ~0)
|
||||
if (CSI->isAllOnesValue())
|
||||
return ReplaceInstUsesWith(I, CSI);
|
||||
}
|
||||
|
||||
|
||||
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
|
||||
// If the input is a SHL by the same constant (ashr (shl X, C), C), then we
|
||||
// have a sign-extend idiom.
|
||||
|
@ -977,8 +977,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
|
||||
return Constant::getNullValue(C1->getType()); // X lshr undef -> 0
|
||||
// undef lshr X -> 0
|
||||
case Instruction::AShr:
|
||||
if (!isa<UndefValue>(C2))
|
||||
return C1; // undef ashr X --> undef
|
||||
if (!isa<UndefValue>(C2)) // undef ashr X --> all ones
|
||||
return Constant::getAllOnesValue(C1->getType());
|
||||
else if (isa<UndefValue>(C1))
|
||||
return C1; // undef ashr undef -> undef
|
||||
else
|
||||
|
@ -35,18 +35,32 @@ define i32 @test4(i8 %A) {
|
||||
|
||||
define i32 @test5(i32 %A) {
|
||||
; CHECK: @test5
|
||||
; CHECK: ret i32 0
|
||||
; CHECK: ret i32 undef
|
||||
%B = lshr i32 %A, 32 ;; shift all bits out
|
||||
ret i32 %B
|
||||
}
|
||||
|
||||
define i32 @test5a(i32 %A) {
|
||||
; CHECK: @test5a
|
||||
; CHECK: ret i32 0
|
||||
; CHECK: ret i32 undef
|
||||
%B = shl i32 %A, 32 ;; shift all bits out
|
||||
ret i32 %B
|
||||
}
|
||||
|
||||
define i32 @test5b() {
|
||||
; CHECK: @test5b
|
||||
; CHECK: ret i32 -1
|
||||
%B = ashr i32 undef, 2 ;; top two bits must be equal, so not undef
|
||||
ret i32 %B
|
||||
}
|
||||
|
||||
define i32 @test5b2(i32 %A) {
|
||||
; CHECK: @test5b2
|
||||
; CHECK: ret i32 -1
|
||||
%B = ashr i32 undef, %A ;; top %A bits must be equal, so not undef
|
||||
ret i32 %B
|
||||
}
|
||||
|
||||
define i32 @test6(i32 %A) {
|
||||
; CHECK: @test6
|
||||
; CHECK-NEXT: mul i32 %A, 6
|
||||
|
Loading…
Reference in New Issue
Block a user