/// Try to use \p Inst's value range from \p Solver to infer the NUW flag.
static bool refineInstruction(SCCPSolver &Solver,
- const SmallPtrSetImpl<Value *> &InsertedValues,
Instruction &Inst) {
if (!isa<OverflowingBinaryOperator>(Inst))
return false;
- auto GetRange = [&Solver, &InsertedValues](Value *Op) {
+ auto GetRange = [&Solver](Value *Op) {
if (auto *Const = dyn_cast<ConstantInt>(Op))
return ConstantRange(Const->getValue());
- if (isa<Constant>(Op) || InsertedValues.contains(Op)) {
+ if (isa<Constant>(Op)) {
unsigned Bitwidth = Op->getType()->getScalarSizeInBits();
return ConstantRange::getFull(Bitwidth);
}
/// Try to replace signed instructions with their unsigned equivalent.
static bool replaceSignedInst(SCCPSolver &Solver,
- SmallPtrSetImpl<Value *> &InsertedValues,
Instruction &Inst) {
// Determine if a signed value is known to be >= 0.
auto isNonNegative = [&Solver](Value *V) {
case Instruction::SExt: {
// If the source value is not negative, this is a zext.
Value *Op0 = Inst.getOperand(0);
- if (InsertedValues.count(Op0) || !isNonNegative(Op0))
+ if (!isNonNegative(Op0))
return false;
NewInst = new ZExtInst(Op0, Inst.getType(), "", &Inst);
break;
case Instruction::AShr: {
// If the shifted value is not negative, this is a logical shift right.
Value *Op0 = Inst.getOperand(0);
- if (InsertedValues.count(Op0) || !isNonNegative(Op0))
+ if (!isNonNegative(Op0))
return false;
NewInst = BinaryOperator::CreateLShr(Op0, Inst.getOperand(1), "", &Inst);
break;
case Instruction::SRem: {
// If both operands are not negative, this is the same as udiv/urem.
Value *Op0 = Inst.getOperand(0), *Op1 = Inst.getOperand(1);
- if (InsertedValues.count(Op0) || InsertedValues.count(Op1) ||
- !isNonNegative(Op0) || !isNonNegative(Op1))
+ if (!isNonNegative(Op0) || !isNonNegative(Op1))
return false;
auto NewOpcode = Inst.getOpcode() == Instruction::SDiv ? Instruction::UDiv
: Instruction::URem;
// Wire up the new instruction and update state.
assert(NewInst && "Expected replacement instruction");
NewInst->takeName(&Inst);
- InsertedValues.insert(NewInst);
Inst.replaceAllUsesWith(NewInst);
- Solver.removeLatticeValueFor(&Inst);
+ Solver.moveLatticeValue(&Inst, NewInst);
Inst.eraseFromParent();
return true;
}
bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB,
- SmallPtrSetImpl<Value *> &InsertedValues,
Statistic &InstRemovedStat,
Statistic &InstReplacedStat) {
bool MadeChanges = false;
MadeChanges = true;
++InstRemovedStat;
- } else if (replaceSignedInst(*this, InsertedValues, Inst)) {
+ } else if (replaceSignedInst(*this, Inst)) {
MadeChanges = true;
++InstReplacedStat;
- } else if (refineInstruction(*this, InsertedValues, Inst)) {
+ } else if (refineInstruction(*this, Inst)) {
MadeChanges = true;
}
}
return StructValues;
}
- void removeLatticeValueFor(Value *V) { ValueState.erase(V); }
+ void moveLatticeValue(Value *From, Value *To) {
+ assert(ValueState.count(From) && "From is not existed in ValueState");
+ ValueState[To] = ValueState[From];
+ ValueState.erase(From);
+ }
/// Invalidate the Lattice Value of \p Call and its users after specializing
/// the call. Then recompute it.
return Visitor->getStructLatticeValueFor(V);
}
-void SCCPSolver::removeLatticeValueFor(Value *V) {
- return Visitor->removeLatticeValueFor(V);
+void SCCPSolver::moveLatticeValue(Value *From, Value *To) {
+ return Visitor->moveLatticeValue(From, To);
}
void SCCPSolver::resetLatticeValueFor(CallBase *Call) {
; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
; CHECK: then:
; CHECK-NEXT: [[SEXT:%.*]] = zext i8 [[A]] to i16
-; CHECK-NEXT: [[ADD_1:%.*]] = add i16 [[SEXT]], 1
-; CHECK-NEXT: [[ADD_2:%.*]] = add i16 [[SEXT]], -128
-; CHECK-NEXT: [[ADD_3:%.*]] = add i16 [[SEXT]], -127
+; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i16 [[SEXT]], 1
+; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i16 [[SEXT]], -128
+; CHECK-NEXT: [[ADD_3:%.*]] = add nsw i16 [[SEXT]], -127
; CHECK-NEXT: [[RES_1:%.*]] = xor i16 [[ADD_1]], [[ADD_2]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i16 [[RES_1]], [[ADD_3]]
; CHECK-NEXT: ret i16 [[RES_2]]
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[COND4]] to i16
; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
; CHECK: then:
-; CHECK-NEXT: [[ADD:%.*]] = add i16 1, [[CONV]]
+; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 1, [[CONV]]
; CHECK-NEXT: ret i16 [[ADD]]
; CHECK: else:
; CHECK-NEXT: ret i16 0