diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index f317252a00d..8fecd6904c3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -1197,17 +1197,12 @@ static Instruction *foldSelectShuffleWith1Binop(ShuffleVectorInst &Shuf) { else return nullptr; - auto *BO = cast<BinaryOperator>(Op0IsBinop ? Op0 : Op1); - Value *X = Op0IsBinop ? Op1 : Op0; - // TODO: Allow div/rem by accounting for potential UB due to undef elements. - if (BO->isIntDivRem()) - return nullptr; - // The identity constant for a binop leaves a variable operand unchanged. For // a vector, this is a splat of something like 0, -1, or 1. // If there's no identity constant for this binop, we're done. + auto *BO = cast<BinaryOperator>(Op0IsBinop ? Op0 : Op1); BinaryOperator::BinaryOps BOpcode = BO->getOpcode(); - Constant *IdC = ConstantExpr::getBinOpIdentity(BOpcode, Shuf.getType()); + Constant *IdC = ConstantExpr::getBinOpIdentity(BOpcode, Shuf.getType(), true); if (!IdC) return nullptr; @@ -1219,14 +1214,22 @@ static Instruction *foldSelectShuffleWith1Binop(ShuffleVectorInst &Shuf) { Constant *NewC = Op0IsBinop ? ConstantExpr::getShuffleVector(C, IdC, Mask) : ConstantExpr::getShuffleVector(IdC, C, Mask); + bool MightCreatePoisonOrUB = + Mask->containsUndefElement() && + (Instruction::isIntDivRem(BOpcode) || Instruction::isShift(BOpcode)); + if (MightCreatePoisonOrUB) + NewC = getSafeVectorConstantForBinop(BOpcode, NewC, true); + // shuf (bop X, C), X, M --> bop X, C' // shuf X, (bop X, C), M --> bop X, C' + Value *X = Op0IsBinop ? Op1 : Op0; Instruction *NewBO = BinaryOperator::Create(BOpcode, X, NewC); NewBO->copyIRFlags(BO); // An undef shuffle mask element may propagate as an undef constant element in // the new binop. That would produce poison where the original code might not. - if (Mask->containsUndefElement()) + // If we already made a safe constant, then there's no danger. + if (Mask->containsUndefElement() && !MightCreatePoisonOrUB) NewBO->dropPoisonGeneratingFlags(); return NewBO; } |

