43 if ((
delta == 0.0) || forwards != (
delta > 0.0)) {
49 if (inclusive && (
count == iterations)) {
63 std::unique_ptr<Expression>* loopTest,
70 auto loopInfo = std::make_unique<LoopUnrollInfo>();
75 if (!loopInitializer) {
77 errors.error(
pos,
"missing init declaration");
86 errors.error(loopInitializer->
fPosition,
"invalid type for loop index");
90 errors.error(loopInitializer->
fPosition,
"invalid type for loop index");
93 if (!initDecl.
value()) {
94 errors.error(loopInitializer->
fPosition,
"missing loop index initializer");
99 "loop index initializer must be a constant expression");
103 loopInfo->fIndex = initDecl.
var();
105 auto is_loop_index = [&](
const std::unique_ptr<Expression>& expr) {
113 if (!loopTest || !*loopTest) {
119 errors.error(loopTest->get()->fPosition,
"invalid condition");
123 if (!is_loop_index(cond->
left())) {
124 errors.error(cond->
fPosition,
"expected loop index on left hand side of condition");
130 case Operator::Kind::GTEQ:
132 case Operator::Kind::LTEQ:
133 case Operator::Kind::EQEQ:
134 case Operator::Kind::NEQ:
142 errors.error(cond->
fPosition,
"loop index must be compared with a constant expression");
157 errors.error(
pos,
"missing loop expression");
160 switch (loopNext->
kind()) {
161 case Expression::Kind::kBinary: {
163 if (!is_loop_index(
next.left())) {
164 errors.error(loopNext->
fPosition,
"expected loop index in loop expression");
169 "loop index must be modified by a constant expression");
172 switch (
next.getOperator().kind()) {
173 case Operator::Kind::PLUSEQ:
break;
174 case Operator::Kind::MINUSEQ: loopInfo->fDelta = -loopInfo->fDelta;
break;
176 errors.error(loopNext->
fPosition,
"invalid operator in loop expression");
181 case Expression::Kind::kPrefix: {
183 if (!is_loop_index(
next.operand())) {
184 errors.error(loopNext->
fPosition,
"expected loop index in loop expression");
187 switch (
next.getOperator().kind()) {
188 case Operator::Kind::PLUSPLUS: loopInfo->fDelta = 1;
break;
189 case Operator::Kind::MINUSMINUS: loopInfo->fDelta = -1;
break;
191 errors.error(loopNext->
fPosition,
"invalid operator in loop expression");
196 case Expression::Kind::kPostfix: {
198 if (!is_loop_index(
next.operand())) {
199 errors.error(loopNext->
fPosition,
"expected loop index in loop expression");
202 switch (
next.getOperator().kind()) {
203 case Operator::Kind::PLUSPLUS: loopInfo->fDelta = 1;
break;
204 case Operator::Kind::MINUSMINUS: loopInfo->fDelta = -1;
break;
206 errors.error(loopNext->
fPosition,
"invalid operator in loop expression");
222 "loop index must not be modified within body of the loop");
227 loopInfo->fCount = 0;
231 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
236 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
240 case Operator::Kind::LTEQ:
241 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
245 case Operator::Kind::GTEQ:
246 loopInfo->fCount =
calculate_count(loopInfo->fStart, loopEnd, loopInfo->fDelta,
250 case Operator::Kind::NEQ: {
252 loopInfo->fCount =
std::ceil(iterations);
253 if (loopInfo->fCount < 0 || loopInfo->fCount != iterations ||
258 if (loopInfo->fIndex->type().componentType().isFloat()) {
265 cond->
left()->clone(),
267 cond->
right()->clone());
272 case Operator::Kind::EQEQ: {
273 if (loopInfo->fStart == loopEnd) {
275 if (loopInfo->fDelta) {
277 loopInfo->fCount = 1;
284 loopInfo->fCount = 0;
293 errors.error(loopPos,
"loop must guarantee termination in fewer iterations");
static float next(float f)
static constexpr double sk_ieee_double_divide(double numer, double denom)
std::unique_ptr< Expression > & left()
std::unique_ptr< Expression > & right()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > left, Operator op, std::unique_ptr< Expression > right)
Operator getOperator() const
static bool GetConstantValue(const Expression &value, double *out)
const Type & baseType() const
std::unique_ptr< Expression > & value()
const Variable * variable() const
std::unique_ptr< LoopUnrollInfo > GetLoopUnrollInfo(const Context &context, Position pos, const ForLoopPositions &positions, const Statement *loopInitializer, std::unique_ptr< Expression > *loopTestPtr, const Expression *loopNext, const Statement *loopStatement, ErrorReporter *errors)
bool StatementWritesToVariable(const Statement &stmt, const Variable &var)
static constexpr int kLoopTerminationLimit
static int calculate_count(double start, double end, double delta, bool forwards, bool inclusive)
SINT bool isfinite(const Vec< N, T > &v)
SIN Vec< N, float > ceil(const Vec< N, float > &x)
Position conditionPosition