aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp52
1 files changed, 38 insertions, 14 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 75520a0c8d5f..71c763de43b4 100644
--- a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -994,6 +994,24 @@ Instruction *InstCombinerImpl::foldBinopOfSextBoolToSelect(BinaryOperator &BO) {
return SelectInst::Create(X, TVal, FVal);
}
+static Constant *constantFoldOperationIntoSelectOperand(
+ Instruction &I, SelectInst *SI, Value *SO) {
+ auto *ConstSO = dyn_cast<Constant>(SO);
+ if (!ConstSO)
+ return nullptr;
+
+ SmallVector<Constant *> ConstOps;
+ for (Value *Op : I.operands()) {
+ if (Op == SI)
+ ConstOps.push_back(ConstSO);
+ else if (auto *C = dyn_cast<Constant>(Op))
+ ConstOps.push_back(C);
+ else
+ llvm_unreachable("Operands should be select or constant");
+ }
+ return ConstantFoldInstOperands(&I, ConstOps, I.getModule()->getDataLayout());
+}
+
static Value *foldOperationIntoSelectOperand(Instruction &I, Value *SO,
InstCombiner::BuilderTy &Builder) {
if (auto *Cast = dyn_cast<CastInst>(&I))
@@ -1101,8 +1119,17 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
}
}
- Value *NewTV = foldOperationIntoSelectOperand(Op, TV, Builder);
- Value *NewFV = foldOperationIntoSelectOperand(Op, FV, Builder);
+ // Make sure that one of the select arms constant folds successfully.
+ Value *NewTV = constantFoldOperationIntoSelectOperand(Op, SI, TV);
+ Value *NewFV = constantFoldOperationIntoSelectOperand(Op, SI, FV);
+ if (!NewTV && !NewFV)
+ return nullptr;
+
+ // Create an instruction for the arm that did not fold.
+ if (!NewTV)
+ NewTV = foldOperationIntoSelectOperand(Op, TV, Builder);
+ if (!NewFV)
+ NewFV = foldOperationIntoSelectOperand(Op, FV, Builder);
return SelectInst::Create(SI->getCondition(), NewTV, NewFV, "", nullptr, SI);
}
@@ -2774,13 +2801,14 @@ static bool isAllocSiteRemovable(Instruction *AI,
continue;
}
- if (isFreeCall(I, &TLI) && getAllocationFamily(I, &TLI) == Family) {
+ if (getFreedOperand(cast<CallBase>(I), &TLI) == PI &&
+ getAllocationFamily(I, &TLI) == Family) {
assert(Family);
Users.emplace_back(I);
continue;
}
- if (isReallocLikeFn(I, &TLI) &&
+ if (getReallocatedOperand(cast<CallBase>(I), &TLI) == PI &&
getAllocationFamily(I, &TLI) == Family) {
assert(Family);
Users.emplace_back(I);
@@ -2805,7 +2833,7 @@ static bool isAllocSiteRemovable(Instruction *AI,
}
Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) {
- assert(isa<AllocaInst>(MI) || isAllocRemovable(&cast<CallBase>(MI), &TLI));
+ assert(isa<AllocaInst>(MI) || isRemovableAlloc(&cast<CallBase>(MI), &TLI));
// If we have a malloc call which is only used in any amount of comparisons to
// null and free calls, delete the calls and replace the comparisons with true
@@ -3007,9 +3035,7 @@ static Instruction *tryToMoveFreeBeforeNullTest(CallInst &FI,
return &FI;
}
-Instruction *InstCombinerImpl::visitFree(CallInst &FI) {
- Value *Op = FI.getArgOperand(0);
-
+Instruction *InstCombinerImpl::visitFree(CallInst &FI, Value *Op) {
// free undef -> unreachable.
if (isa<UndefValue>(Op)) {
// Leave a marker since we can't modify the CFG here.
@@ -3024,12 +3050,10 @@ Instruction *InstCombinerImpl::visitFree(CallInst &FI) {
// If we had free(realloc(...)) with no intervening uses, then eliminate the
// realloc() entirely.
- if (CallInst *CI = dyn_cast<CallInst>(Op)) {
- if (CI->hasOneUse() && isReallocLikeFn(CI, &TLI)) {
- return eraseInstFromFunction(
- *replaceInstUsesWith(*CI, CI->getOperand(0)));
- }
- }
+ CallInst *CI = dyn_cast<CallInst>(Op);
+ if (CI && CI->hasOneUse())
+ if (Value *ReallocatedOp = getReallocatedOperand(CI, &TLI))
+ return eraseInstFromFunction(*replaceInstUsesWith(*CI, ReallocatedOp));
// If we optimize for code size, try to move the call to free before the null
// test so that simplify cfg can remove the empty block and dead code