Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbae19aa

Browse files
authored
Fold Span.Slice(X) like bound checks (#122040)
[Diffs](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1215131&view=ms.vss-build-web.run-extensions-tab).```cs static Vector256<int> Test(Span<int> values) { if (values.Length < 16) return default; return Vector256.Create(values.Slice(8)); }```Was:```asm; Method Program:Test(System.Span`1[int]):System.Runtime.Intrinsics.Vector256`1[int] (FullOpts) sub rsp, 40 mov rax, bword ptr [rdx] mov edx, dword ptr [rdx+0x08] cmp edx, 16 jl SHORT G_M55981_IG04 add rax, 32 add edx, -8 cmp edx, 8 jl SHORT G_M55981_IG07 vmovups ymm0, ymmword ptr [rax] vmovups ymmword ptr [rcx], ymm0 jmp SHORT G_M55981_IG05G_M55981_IG04: vxorps ymm0, ymm0, ymm0 vmovups ymmword ptr [rcx], ymm0G_M55981_IG05: mov rax, rcx vzeroupper add rsp, 40 ret G_M55981_IG07: mov ecx, 6 call [System.ThrowHelper:ThrowArgumentOutOfRangeException(int)] int3 ; Total bytes of code: 68```Now:```asm; Method Program:Test(System.Span`1[int]):System.Runtime.Intrinsics.Vector256`1[int] (FullOpts) mov rax, bword ptr [rdx] mov edx, dword ptr [rdx+0x08] cmp edx, 16 jl SHORT G_M55981_IG04 add rax, 32 vmovups ymm0, ymmword ptr [rax] vmovups ymmword ptr [rcx], ymm0 jmp SHORT G_M55981_IG05G_M55981_IG04: vxorps ymm0, ymm0, ymm0 vmovups ymmword ptr [rcx], ymm0G_M55981_IG05: mov rax, rcx vzeroupper ret ; Total bytes of code: 40```
1 parent626ad32 commitbae19aa

File tree

2 files changed

+78
-48
lines changed

2 files changed

+78
-48
lines changed

‎src/coreclr/jit/assertionprop.cpp‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4461,6 +4461,36 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions,
44614461
returnoptAssertionProp_Update(newTree, tree, stmt);
44624462
}
44634463
}
4464+
4465+
// If op1VN is actually ADD(X, CNS), we can try peeling the constant offset and adjusting op2Cns accordingly.
4466+
// It's a bit more complicated for unsigned comparisons, so only do it for signed ones for now.
4467+
//
4468+
if (!tree->IsUnsigned())
4469+
{
4470+
ValueNum peeledOp1VN = op1VN;
4471+
int peeledOffset =0;
4472+
vnStore->PeelOffsetsI32(&peeledOp1VN, &peeledOffset);
4473+
4474+
if (peeledOffset !=0)
4475+
{
4476+
Range peeledOffsetRng =Range(Limit(Limit::keConstant, peeledOffset));
4477+
Range peeledOp1Rng =Range(Limit(Limit::keUnknown));
4478+
if (RangeCheck::TryGetRangeFromAssertions(this, peeledOp1VN, assertions, &peeledOp1Rng))
4479+
{
4480+
// Subtract handles overflow internally.
4481+
rng2 =RangeOps::Subtract(rng2, peeledOffsetRng);
4482+
4483+
RangeOps::RelationKind kind =
4484+
RangeOps::EvalRelop(tree->OperGet(), tree->IsUnsigned(), peeledOp1Rng, rng2);
4485+
if ((kind != RangeOps::RelationKind::Unknown))
4486+
{
4487+
newTree = kind == RangeOps::RelationKind::AlwaysTrue ?gtNewTrue() :gtNewFalse();
4488+
newTree =gtWrapWithSideEffects(newTree, tree, GTF_ALL_EFFECT);
4489+
returnoptAssertionProp_Update(newTree, tree, stmt);
4490+
}
4491+
}
4492+
}
4493+
}
44644494
}
44654495

44664496
// Else check if we have an equality check involving a local or an indir

‎src/coreclr/jit/rangecheck.h‎

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,25 @@ struct RangeOps
328328
returnLimit(Limit::keUnknown);
329329
}
330330

331+
// Perform 'value' - 'cns'
332+
staticLimitSubtractConstantLimit(constLimit&value,constLimit&cns)
333+
{
334+
assert(cns.IsConstant());
335+
336+
if (cns.GetConstant()==INT_MIN)
337+
{
338+
// Subtracting INT_MIN would overflow
339+
returnLimit(Limit::keUnknown);
340+
}
341+
342+
Limitl=value;
343+
if (l.AddConstant(-cns.GetConstant()))
344+
{
345+
returnl;
346+
}
347+
returnLimit(Limit::keUnknown);
348+
}
349+
331350
// Perform 'value' * 'cns'
332351
staticLimitMultiplyConstantLimit(constLimit&value,constLimit&cns)
333352
{
@@ -352,9 +371,9 @@ struct RangeOps
352371
returnLimit(Limit::keUnknown);
353372
}
354373

355-
// Given two ranges "r1" and "r2", performan addoperation on the
356-
// ranges.
357-
staticRangeAdd(Range&r1,Range&r2)
374+
// Given two ranges "r1" and "r2", performa generic 'op'operation on the ranges.
375+
template<typenameOperation>
376+
staticRangeApplyRangeOp(Range&r1,Range&r2,Operationop)
358377
{
359378
Limit&r1lo=r1.LowerLimit();
360379
Limit&r1hi=r1.UpperLimit();
@@ -376,23 +395,45 @@ struct RangeOps
376395

377396
if (r1lo.IsConstant())
378397
{
379-
result.lLimit=AddConstantLimit(r2lo,r1lo);
398+
result.lLimit=op(r2lo,r1lo);
380399
}
381400
if (r2lo.IsConstant())
382401
{
383-
result.lLimit=AddConstantLimit(r1lo,r2lo);
402+
result.lLimit=op(r1lo,r2lo);
384403
}
385404
if (r1hi.IsConstant())
386405
{
387-
result.uLimit=AddConstantLimit(r2hi,r1hi);
406+
result.uLimit=op(r2hi,r1hi);
388407
}
389408
if (r2hi.IsConstant())
390409
{
391-
result.uLimit=AddConstantLimit(r1hi,r2hi);
410+
result.uLimit=op(r1hi,r2hi);
392411
}
412+
393413
returnresult;
394414
}
395415

416+
staticRangeAdd(Range&r1,Range&r2)
417+
{
418+
returnApplyRangeOp(r1,r2, [](Limit&a,Limit&b) {
419+
returnAddConstantLimit(a,b);
420+
});
421+
}
422+
423+
staticRangeSubtract(Range&r1,Range&r2)
424+
{
425+
returnApplyRangeOp(r1,r2, [](Limit&a,Limit&b) {
426+
returnSubtractConstantLimit(a,b);
427+
});
428+
}
429+
430+
staticRangeMultiply(Range&r1,Range&r2)
431+
{
432+
returnApplyRangeOp(r1,r2, [](Limit&a,Limit&b) {
433+
returnMultiplyConstantLimit(a,b);
434+
});
435+
}
436+
396437
staticRangeShiftRight(Range&r1,Range&r2)
397438
{
398439
Limit&r1lo=r1.LowerLimit();
@@ -430,47 +471,6 @@ struct RangeOps
430471
returnresult;
431472
}
432473

433-
// Given two ranges "r1" and "r2", perform an multiply operation on the
434-
// ranges.
435-
staticRangeMultiply(Range&r1,Range&r2)
436-
{
437-
Limit&r1lo=r1.LowerLimit();
438-
Limit&r1hi=r1.UpperLimit();
439-
Limit&r2lo=r2.LowerLimit();
440-
Limit&r2hi=r2.UpperLimit();
441-
442-
Rangeresult=Limit(Limit::keUnknown);
443-
444-
// Check lo ranges if they are dependent and not unknown.
445-
if ((r1lo.IsDependent()&& !r1lo.IsUnknown())|| (r2lo.IsDependent()&& !r2lo.IsUnknown()))
446-
{
447-
result.lLimit=Limit(Limit::keDependent);
448-
}
449-
// Check hi ranges if they are dependent and not unknown.
450-
if ((r1hi.IsDependent()&& !r1hi.IsUnknown())|| (r2hi.IsDependent()&& !r2hi.IsUnknown()))
451-
{
452-
result.uLimit=Limit(Limit::keDependent);
453-
}
454-
455-
if (r1lo.IsConstant())
456-
{
457-
result.lLimit=MultiplyConstantLimit(r2lo,r1lo);
458-
}
459-
if (r2lo.IsConstant())
460-
{
461-
result.lLimit=MultiplyConstantLimit(r1lo,r2lo);
462-
}
463-
if (r1hi.IsConstant())
464-
{
465-
result.uLimit=MultiplyConstantLimit(r2hi,r1hi);
466-
}
467-
if (r2hi.IsConstant())
468-
{
469-
result.uLimit=MultiplyConstantLimit(r1hi,r2hi);
470-
}
471-
returnresult;
472-
}
473-
474474
// Given two ranges "r1" and "r2", do a Phi merge. If "monIncreasing" is true,
475475
// then ignore the dependent variables for the lower bound but not for the upper bound.
476476
staticRangeMerge(constRange&r1,constRange&r2,boolmonIncreasing)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp