@@ -422,6 +422,10 @@ namespace {
422
422
BasicBlock *BB);
423
423
Optional<ConstantRange> getRangeForOperand (unsigned Op, Instruction *I,
424
424
BasicBlock *BB);
425
+ bool solveBlockValueBinaryOpImpl (
426
+ ValueLatticeElement &BBLV, Instruction *I, BasicBlock *BB,
427
+ std::function<ConstantRange(const ConstantRange &,
428
+ const ConstantRange &)> OpFn);
425
429
bool solveBlockValueBinaryOp (ValueLatticeElement &BBLV, BinaryOperator *BBI,
426
430
BasicBlock *BB);
427
431
bool solveBlockValueCast (ValueLatticeElement &BBLV, CastInst *CI,
@@ -1040,6 +1044,26 @@ bool LazyValueInfoImpl::solveBlockValueCast(ValueLatticeElement &BBLV,
1040
1044
return true ;
1041
1045
}
1042
1046
1047
+ bool LazyValueInfoImpl::solveBlockValueBinaryOpImpl (
1048
+ ValueLatticeElement &BBLV, Instruction *I, BasicBlock *BB,
1049
+ std::function<ConstantRange(const ConstantRange &,
1050
+ const ConstantRange &)> OpFn) {
1051
+ // Figure out the ranges of the operands. If that fails, use a
1052
+ // conservative range, but apply the transfer rule anyways. This
1053
+ // lets us pick up facts from expressions like "and i32 (call i32
1054
+ // @foo()), 32"
1055
+ Optional<ConstantRange> LHSRes = getRangeForOperand (0 , I, BB);
1056
+ Optional<ConstantRange> RHSRes = getRangeForOperand (1 , I, BB);
1057
+ if (!LHSRes.hasValue () || !RHSRes.hasValue ())
1058
+ // More work to do before applying this transfer rule.
1059
+ return false ;
1060
+
1061
+ ConstantRange LHSRange = LHSRes.getValue ();
1062
+ ConstantRange RHSRange = RHSRes.getValue ();
1063
+ BBLV = ValueLatticeElement::getRange (OpFn (LHSRange, RHSRange));
1064
+ return true ;
1065
+ }
1066
+
1043
1067
bool LazyValueInfoImpl::solveBlockValueBinaryOp (ValueLatticeElement &BBLV,
1044
1068
BinaryOperator *BO,
1045
1069
BasicBlock *BB) {
@@ -1060,36 +1084,17 @@ bool LazyValueInfoImpl::solveBlockValueBinaryOp(ValueLatticeElement &BBLV,
1060
1084
case Instruction::AShr:
1061
1085
case Instruction::And:
1062
1086
case Instruction::Or:
1063
- // continue into the code below
1064
- break ;
1087
+ return solveBlockValueBinaryOpImpl (BBLV, BO, BB,
1088
+ [BO](const ConstantRange &CR1, const ConstantRange &CR2) {
1089
+ return CR1.binaryOp (BO->getOpcode (), CR2);
1090
+ });
1065
1091
default :
1066
1092
// Unhandled instructions are overdefined.
1067
1093
LLVM_DEBUG (dbgs () << " compute BB '" << BB->getName ()
1068
1094
<< " ' - overdefined (unknown binary operator).\n " );
1069
1095
BBLV = ValueLatticeElement::getOverdefined ();
1070
1096
return true ;
1071
1097
};
1072
-
1073
- // Figure out the ranges of the operands. If that fails, use a
1074
- // conservative range, but apply the transfer rule anyways. This
1075
- // lets us pick up facts from expressions like "and i32 (call i32
1076
- // @foo()), 32"
1077
- Optional<ConstantRange> LHSRes = getRangeForOperand (0 , BO, BB);
1078
- Optional<ConstantRange> RHSRes = getRangeForOperand (1 , BO, BB);
1079
-
1080
- if (!LHSRes.hasValue () || !RHSRes.hasValue ())
1081
- // More work to do before applying this transfer rule.
1082
- return false ;
1083
-
1084
- ConstantRange LHSRange = LHSRes.getValue ();
1085
- ConstantRange RHSRange = RHSRes.getValue ();
1086
-
1087
- // NOTE: We're currently limited by the set of operations that ConstantRange
1088
- // can evaluate symbolically. Enhancing that set will allows us to analyze
1089
- // more definitions.
1090
- Instruction::BinaryOps BinOp = BO->getOpcode ();
1091
- BBLV = ValueLatticeElement::getRange (LHSRange.binaryOp (BinOp, RHSRange));
1092
- return true ;
1093
1098
}
1094
1099
1095
1100
static ValueLatticeElement getValueFromICmpCondition (Value *Val, ICmpInst *ICI,
0 commit comments