Runtime: Can "Math.DivRem" do division operation only once?

Created on 21 Apr 2015  路  10Comments  路  Source: dotnet/runtime

Currently it does division twice, but most CPUs support to get the two values by doing division only once.
Besides,this method should support uint and ulong too.

category:cq
theme:div-mod-rem
skill-level:expert
cost:large

JitUntriaged area-CodeGen-coreclr enhancement optimization tenet-performance

Most helpful comment

@CarolEidt
Is there any progress about this?

All 10 comments

Math.DivRem is not in the .NET Core public surface, but I agree that it would be nice for the code generators to recognize the pattern and perform the division just one.

cc @CarolEidt @cmckinsey

cc: @KrzysztofCwalina, as IIRC, Krzysztof bumped up against this as a measurable cost when doing some recent fomatting/parsing experimentation.

This would not be a very difficult pattern to recognize: a div and a rem with incoming value numbers that match, though it doesn't "fit" with any existing (or other common) optimization patterns. The thing that would be challenging would be to deal with the resulting IR node that would produce two values in registers. Although that would not be all that difficult, it would require more pervasive changes.

:+1:

In short term, couldn't Math.DivRem be treated as a special-case (intrinsic)? I wouldn't think that this optimization wouldn't really require many changes.

Long term though, adding an optimization pattern to recognize / and % with matching value members would be great.

@tannergooding - you would think that it would be simpler, but actually it requires the messiest part of the work (handling the node in the IR that produces two values), while only relieving the JIT of what is probably the more straightforward part of the implementation. It might actually be easier on x86 (32 bit) where we already have to deal with longs that occupy multiple registers.

@CarolEidt, I'm actually wondering why this would require more pervasive changes?

I would think that instructions like idiv should already document (via some metadata) that they end up writing two registers, correct? As without this being carried around by the code generator, it would potentially end up overwriting the second argument of the parameter list whenever it generates the idiv instruction.

I've not looked at the code, but I would guess that various instructions do indicate what registers end up being input/output by the instruction and that the changes here would be to allow the node to actually carry the second value (which could probably be done via inheritance and type checking). I actually think this is in a similar vein to having an intrinsic that takes 3 arguments where the GenTreeOp currently only allows 2 arguments.

@CarolEidt
Is there any progress about this?

@tannergooding @CarolEidt
After more than five years, has this issue been solved?

No, but .NET 5 brought about some register allocator changes that should (hopefully) make it simpler to support now.

Before this is addressed in .NET 5, any remedies we could do ourselves. e.g. is it possible to roll our own DivRem method to achieve doing division only once?

Was this page helpful?
0 / 5 - 0 ratings