mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
[InstCombine] rename SimplifyDivRemOfSelect to be clearer, add comments, simplify code; NFCI
There's at least one bug here - this code can fail with vector types (PR34856). It's also being called for FREM; I'm still trying to understand how that is valid. llvm-svn: 315127
This commit is contained in:
parent
ab48678342
commit
4f6fd5fe68
@ -277,7 +277,7 @@ public:
|
||||
Instruction *visitURem(BinaryOperator &I);
|
||||
Instruction *visitSRem(BinaryOperator &I);
|
||||
Instruction *visitFRem(BinaryOperator &I);
|
||||
bool SimplifyDivRemOfSelect(BinaryOperator &I);
|
||||
bool simplifyDivRemOfSelectWithZeroOp(BinaryOperator &I);
|
||||
Instruction *commonRemTransforms(BinaryOperator &I);
|
||||
Instruction *commonIRemTransforms(BinaryOperator &I);
|
||||
Instruction *commonDivTransforms(BinaryOperator &I);
|
||||
|
@ -778,24 +778,23 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
|
||||
return Changed ? &I : nullptr;
|
||||
}
|
||||
|
||||
/// Try to fold a divide or remainder of a select instruction.
|
||||
bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) {
|
||||
SelectInst *SI = cast<SelectInst>(I.getOperand(1));
|
||||
|
||||
// div/rem X, (Cond ? 0 : Y) -> div/rem X, Y
|
||||
int NonNullOperand = -1;
|
||||
if (Constant *ST = dyn_cast<Constant>(SI->getOperand(1)))
|
||||
if (ST->isNullValue())
|
||||
NonNullOperand = 2;
|
||||
// div/rem X, (Cond ? Y : 0) -> div/rem X, Y
|
||||
if (Constant *ST = dyn_cast<Constant>(SI->getOperand(2)))
|
||||
if (ST->isNullValue())
|
||||
NonNullOperand = 1;
|
||||
|
||||
if (NonNullOperand == -1)
|
||||
/// Fold a divide or remainder with a select instruction divisor when one of the
|
||||
/// select operands is zero. In that case, we can use the other select operand
|
||||
/// because div/rem by zero is undefined.
|
||||
bool InstCombiner::simplifyDivRemOfSelectWithZeroOp(BinaryOperator &I) {
|
||||
SelectInst *SI = dyn_cast<SelectInst>(I.getOperand(1));
|
||||
if (!SI)
|
||||
return false;
|
||||
|
||||
Value *SelectCond = SI->getOperand(0);
|
||||
int NonNullOperand;
|
||||
if (match(SI->getTrueValue(), m_Zero()))
|
||||
// div/rem X, (Cond ? 0 : Y) -> div/rem X, Y
|
||||
NonNullOperand = 2;
|
||||
else if (match(SI->getFalseValue(), m_Zero()))
|
||||
// div/rem X, (Cond ? Y : 0) -> div/rem X, Y
|
||||
NonNullOperand = 1;
|
||||
else
|
||||
return false;
|
||||
|
||||
// Change the div/rem to use 'Y' instead of the select.
|
||||
I.setOperand(1, SI->getOperand(NonNullOperand));
|
||||
@ -808,6 +807,7 @@ bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) {
|
||||
|
||||
// If the select and condition only have a single use, don't bother with this,
|
||||
// early exit.
|
||||
Value *SelectCond = SI->getCondition();
|
||||
if (SI->use_empty() && SelectCond->hasOneUse())
|
||||
return true;
|
||||
|
||||
@ -863,7 +863,7 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
|
||||
|
||||
// Handle cases involving: [su]div X, (select Cond, Y, Z)
|
||||
// This does not apply for fdiv.
|
||||
if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I))
|
||||
if (simplifyDivRemOfSelectWithZeroOp(I))
|
||||
return &I;
|
||||
|
||||
if (Instruction *LHS = dyn_cast<Instruction>(Op0)) {
|
||||
@ -1458,7 +1458,7 @@ Instruction *InstCombiner::commonIRemTransforms(BinaryOperator &I) {
|
||||
}
|
||||
|
||||
// Handle cases involving: rem X, (select Cond, Y, Z)
|
||||
if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I))
|
||||
if (simplifyDivRemOfSelectWithZeroOp(I))
|
||||
return &I;
|
||||
|
||||
if (isa<Constant>(Op1)) {
|
||||
@ -1613,7 +1613,7 @@ Instruction *InstCombiner::visitFRem(BinaryOperator &I) {
|
||||
return replaceInstUsesWith(I, V);
|
||||
|
||||
// Handle cases involving: rem X, (select Cond, Y, Z)
|
||||
if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I))
|
||||
if (simplifyDivRemOfSelectWithZeroOp(I))
|
||||
return &I;
|
||||
|
||||
return nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user