reames (Philip Reames)
User

Projects

User does not belong to any projects.

User Details

User Since
Oct 23 2013, 6:32 PM (212 w, 6 d)

Recent Activity

Yesterday

reames accepted D39453: [SCEV] Strengthen variance condition in calculateLoopDisposition.

LGTM

Tue, Nov 21, 8:21 PM

Tue, Nov 14

reames requested changes to D39453: [SCEV] Strengthen variance condition in calculateLoopDisposition.

Max and I discussed and realized this comes down to simply needing a much simpler and straight-forward comment. :) If AR is not defined on entry to L, it can't be LoopInvariant with respect to L. The distinction between L being a parent of AR->loop vs a sibling vs a nephew, cousin, etc... really doesn't contribute anything here.

Tue, Nov 14, 9:05 PM
reames accepted D39236: [SCEV][NFC] Introduce isSafeToExpandAt function to SCEVExpander.

LGTM

Tue, Nov 14, 8:31 PM

Tue, Nov 7

reames added a comment to D39743: [ValueLattice] Add CompactValueLatticeElement..

Structural suggestion: pick either of the two subtasks and implement them in isolation. That is *either* replace the ConstantRange with an owned ConstantRange allocation and implement the tagged pointer OR implement the ConstantRange folding set. Doing both in one change is needlessly complicated. Once one is done, the other follows more naturally. I'd suggest the first then the second, but either order is defensible.

Tue, Nov 7, 4:16 PM
reames added a reviewer for D39743: [ValueLattice] Add CompactValueLatticeElement.: anna.
Tue, Nov 7, 4:16 PM
reames accepted D39234: [IRCE] Fix SCEVExpander's usage in IRCE.

LGTM once dependent changes land.

Tue, Nov 7, 4:05 PM
reames requested changes to D39236: [SCEV][NFC] Introduce isSafeToExpandAt function to SCEVExpander.

relatively minor code comments.

Tue, Nov 7, 4:03 PM
reames added a comment to D39453: [SCEV] Strengthen variance condition in calculateLoopDisposition.

Max, I don't quite follow your discussion enough to know for sure, but I suspect there's something wrong with your framing here. A induction variable in one loop may be loop invariant with respect to sibling loop. That's normal. Is there maybe a subcase here? Or are you looking at flawed assumption in caller code?

Tue, Nov 7, 3:58 PM
reames accepted D39589: [IRCE] Remove folding of two range checks into RANGE_CHECK_BOTH.

LGTM, but please land a day or two separate from any other change. i.e. if this exposes problems (pass ordering?) let's make that obvious.

Tue, Nov 7, 3:50 PM
reames accepted D39590: [IRCE][NFC] Make range check's End a non-null SCEV.

LGTM once dependent revisions have been in tree for a couple of days.

Tue, Nov 7, 3:46 PM

Wed, Nov 1

reames committed rL317116: Revert 317016 and 317048.
Revert 317016 and 317048
Wed, Nov 1, 12:49 PM
reames added a reverting commit for rL317048: [SimplifyIndVar] Inline makIVComparisonInvariant to eleminate code duplication…: rL317116: Revert 317016 and 317048.
Wed, Nov 1, 12:49 PM
reames added a reverting commit for rL317016: [IndVarSimplify] Extract wrapper around SE-.isLoopInvariantPredicate [NFC]: rL317116: Revert 317016 and 317048.
Wed, Nov 1, 12:49 PM

Tue, Oct 31

reames committed rL317048: [SimplifyIndVar] Inline makIVComparisonInvariant to eleminate code duplication….
[SimplifyIndVar] Inline makIVComparisonInvariant to eleminate code duplication…
Tue, Oct 31, 3:56 PM
reames committed rL317016: [IndVarSimplify] Extract wrapper around SE-.isLoopInvariantPredicate [NFC].
[IndVarSimplify] Extract wrapper around SE-.isLoopInvariantPredicate [NFC]
Tue, Oct 31, 11:05 AM
reames committed rL317012: [IndVarSimplify] Simplify code using a dictionary.
[IndVarSimplify] Simplify code using a dictionary
Tue, Oct 31, 10:07 AM

Mon, Oct 30

reames committed rL316976: [IndVarSimplify] Simplify code using preheader assumption.
[IndVarSimplify] Simplify code using preheader assumption
Mon, Oct 30, 10:17 PM
reames committed rL316974: [SimplifyIndVar] Extract out invariant expression handling.
[SimplifyIndVar] Extract out invariant expression handling
Mon, Oct 30, 9:19 PM
reames accepted D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.

LGTM

Mon, Oct 30, 9:14 PM
reames committed rL316968: Undo accidental commit.
Undo accidental commit
Mon, Oct 30, 5:04 PM
reames committed rL316967: [CGP] Fix crash on i96 bit multiply.
[CGP] Fix crash on i96 bit multiply
Mon, Oct 30, 5:00 PM
reames requested changes to D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.
Mon, Oct 30, 10:47 AM
reames accepted D39414: [IRCE][NFC] Rename fields of InductiveRangeCheck.

LGTM

Mon, Oct 30, 10:40 AM

Sun, Oct 29

reames added inline comments to D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.
Sun, Oct 29, 11:28 PM

Fri, Oct 27

reames requested changes to D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.

Ok, once more very close. Thank you for working through the issues raised and splitting out the various bits. Now that's done, one more round of updates and we should be good for a resubmit.

Fri, Oct 27, 9:51 AM
reames accepted D39369: [GVN][NFC] Mark instruction for deletion instead of immediate erasing in LoadPRE.

LGTM w/comment applied.

Fri, Oct 27, 9:35 AM

Thu, Oct 26

reames committed rL316709: [SimplifyIndVars] Shorten code by using SCEV helper [NFC].
[SimplifyIndVars] Shorten code by using SCEV helper [NFC]
Thu, Oct 26, 3:02 PM
reames added inline comments to D38944: [GVN] Handle removal of first implicit CF instruction correctly.
Thu, Oct 26, 2:50 PM
reames committed rL316699: [LICM] Restructure implicit exit handling to be more clear [NFCI].
[LICM] Restructure implicit exit handling to be more clear [NFCI]
Thu, Oct 26, 2:00 PM
reames requested changes to D38944: [GVN] Handle removal of first implicit CF instruction correctly.
Thu, Oct 26, 10:18 AM
reames requested changes to D39320: [IRCE] Ensure that expanded exit values are available in loop's preheader.
Thu, Oct 26, 9:28 AM

Mon, Oct 23

reames added inline comments to D38581: [IRCE] Fix intersection between signed and unsigned ranges.
Mon, Oct 23, 1:45 PM

Oct 20 2017

reames accepted D39103: [RISCV 12.5/n] Codegen support for memory operations on global addresses.

LGTM

Oct 20 2017, 4:03 PM
reames accepted D29934: [RISCV 12/n] Codegen support for memory operations.

Thanks for splitting. Tracking the pieces is now much easier.

Oct 20 2017, 3:57 PM
reames accepted D39101: [RISCV 11.5/n] Codegen support for materializing constants.

LGTM

Oct 20 2017, 3:56 PM

Oct 18 2017

reames requested changes to D29934: [RISCV 12/n] Codegen support for memory operations.
Oct 18 2017, 4:58 PM
reames accepted D29938: [RISCV 16/n] Support and tests for a variety of additional LLVM IR constructs.

LGTM w/identified issues fixed before submission.

Oct 18 2017, 4:53 PM

Oct 16 2017

reames closed D38987: [GVN] Revert rL315440.

Sending include/llvm/Transforms/Scalar/GVN.h
Sending lib/Transforms/Scalar/GVN.cpp
Sending test/Transforms/GVN/PRE/pre-load.ll
Transmitting file data ...done
Committing transaction...
Committed revision 315974.

Oct 16 2017, 11:21 PM
reames accepted D38987: [GVN] Revert rL315440.
Oct 16 2017, 11:21 PM
reames committed rL315974: Revert 315440 on behalf of mkazantsev.
Revert 315440 on behalf of mkazantsev
Oct 16 2017, 11:21 PM
reames added a reverting commit for rL315440: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control…: rL315974: Revert 315440 on behalf of mkazantsev.
Oct 16 2017, 11:21 PM

Oct 10 2017

reames requested changes to D35858: [RFC] [LLVM] [LazyValueInfo] Introduce getRecurringEdgeValue to handle simple recurrence.

Pending update per last comment, just getting this off review queue.

Oct 10 2017, 12:06 PM
reames accepted D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.

LGTM

Oct 10 2017, 12:04 PM
reames accepted D38392: Disallow sinking of unordered atomic loads into loops.

LGTM

Oct 10 2017, 12:00 PM

Oct 4 2017

reames added inline comments to D38529: [IRCE] Temporarily disable unsigned latch conditions by default.
Oct 4 2017, 10:44 AM

Oct 3 2017

reames accepted D38529: [IRCE] Temporarily disable unsigned latch conditions by default.

LGTM w/the following changes made: add a test case which demonstrates the miscompile and update the description to reference the original problematic commit.

Oct 3 2017, 10:15 PM
reames added inline comments to D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.
Oct 3 2017, 9:57 AM

Oct 2 2017

reames updated subscribers of D29933: [RISCV 11/n] Initial codegen support for ALU operations.
Oct 2 2017, 8:54 PM
reames accepted D29933: [RISCV 11/n] Initial codegen support for ALU operations.

LGTM so as to unblock patches. I don't see anything obviously wrong with these patches though I might be missing details as this is an area I'm not hugely familiar with.

Oct 2 2017, 8:51 PM
reames requested changes to D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.
  • List Item

The loadPRE part of this seems very close to being ready to submit.

Oct 2 2017, 8:21 PM
reames accepted D38278: [CGP] Make optimizeMemoryInst capable of handling multiple AddrModes.

LGTM subject to the comment below being a clear bugfix addressed before commit.

Oct 2 2017, 8:08 PM

Sep 29 2017

reames added a comment to D38392: Disallow sinking of unordered atomic loads into loops.

I see your point now. My concern is performance: if we allow hoisting of atomic load, but not allow sinking it, we may end up with bad performance as we may have too much redundant atomic loads in the preheader. Any suggestions on how to solve that?

Not really. I can say that we've been running performance tests for months in this configuration (LICM hoisting unordered loads, no LoopSink) without noticing any problems. I'm not immediately concerned.

Sorry, not sure if I follow the logic, could you explain why you don't think this is a performance concern?

I acknowledge it's a potential issue. I have no good ideas for a solution. I don't believe it's a current problem and evidence to believe that it's relatively minor. (i.e. we haven't seen it)

Sep 29 2017, 6:00 PM
reames added a comment to D38392: Disallow sinking of unordered atomic loads into loops.

I see your point now. My concern is performance: if we allow hoisting of atomic load, but not allow sinking it, we may end up with bad performance as we may have too much redundant atomic loads in the preheader. Any suggestions on how to solve that?

Not really. I can say that we've been running performance tests for months in this configuration (LICM hoisting unordered loads, no LoopSink) without noticing any problems. I'm not immediately concerned.

Sep 29 2017, 5:21 PM
reames added a comment to D38392: Disallow sinking of unordered atomic loads into loops.

In the following example:

while(true) {

a1 = foo();
bar(a1);
while(true) {
  if (baz())
    return atomic_load(a1);
}

}

The atomic_load(a1) will be executed once without hoisting. But with LICM, it may be called multiple times.

I can't make out your example enough to assess what you're intent is. As a general comment, keep in mind that *loading* multiple times is not a problem if only one of them is *used*.

Sep 29 2017, 3:45 PM
reames added a comment to D38392: Disallow sinking of unordered atomic loads into loops.

How about the following case:

while(c1) {

if (c2)
 atomic_load;

}

Looks like isSafeToExecuteUnconditionally will not prevent the atomic_load from hoisted to preheader. So in real execution, it may introduce extra atomic loads?

From an aliasing/ordering perspective nothing has changed in this example. We have an additional safety requirement (we can't introduce faults), but we haven't changed anything about the memory model legality of the reordering.

Sep 29 2017, 10:16 AM
reames added a comment to D38392: Disallow sinking of unordered atomic loads into loops.

Is it legal to hoist an atomic load out of the loop?

Yes, that strictly reduces the number of loads. You can think of hoisting as reusing the load from the first iteration across future iterations and just moving where in the first iteration that load runs. As long as that repositioning is legal, the rest of the transform is just basic FRE.

Sep 29 2017, 9:11 AM
reames accepted D35431: Extend FindAllMemoryUses for target intrinsics.

LGTM

Sep 29 2017, 9:09 AM
reames requested changes to D38392: Disallow sinking of unordered atomic loads into loops.
Sep 29 2017, 9:01 AM
reames added a comment to D38392: Disallow sinking of unordered atomic loads into loops.

Reviewers: Note that there's a lot of context in previous discussion about the semantics of various types of nonatomic, unordered, and ordered loads in https://reviews.llvm.org/D37463. Comment https://reviews.llvm.org/D37463#882487 is particularly relevant for this review. It's the direct motivation for this patch.

Sep 29 2017, 8:55 AM

Sep 27 2017

reames added a comment to D37463: Fix miscompile in LoopSink pass.

I think there might be some further investigation needed for unordered atomics, but I will take that offline with Daniil before returning to this thread.

Returning to this point, the conclusion I would reach reviewing our Atomics documentation is that sinking an unordered atomic into a loop must be disallowed, because doing so duplicates the load which is disallowed.

Sep 27 2017, 11:56 AM
reames added a comment to D38278: [CGP] Make optimizeMemoryInst capable of handling multiple AddrModes.

p.s. Thanks for doing the work to split this out and being so responsive to review comments. Much appreciated!

Sep 27 2017, 11:13 AM
reames requested changes to D38278: [CGP] Make optimizeMemoryInst capable of handling multiple AddrModes.
Sep 27 2017, 11:13 AM

Sep 26 2017

reames added inline comments to D37648: [SLPVectorizer] Fix PR21780 Expansion of 256 bit vector loads fails to fold into shuffles.
Sep 26 2017, 3:30 PM

Sep 25 2017

reames added inline comments to D36073: [CGP] Extends the scope of optimizeMemoryInst optimization.
Sep 25 2017, 5:02 AM
reames added inline comments to D38133: [CGP] Make optimizeMemoryInst able to combine more kinds of ExtAddrMode fields.
Sep 25 2017, 5:02 AM
reames requested changes to D38133: [CGP] Make optimizeMemoryInst able to combine more kinds of ExtAddrMode fields.

Marking as changes needs to reflect split requested. Note that I really haven't even looked at the guts of the transform and don't plan to until the common pieces have been extracted.

Sep 25 2017, 5:02 AM
reames requested changes to D36073: [CGP] Extends the scope of optimizeMemoryInst optimization.

Marking as changes needs to reflect split requested. Note that I really haven't even looked at the guts of the transform and don't plan to until the common pieces have been extracted.

Sep 25 2017, 5:02 AM
reames added a comment to D38133: [CGP] Make optimizeMemoryInst able to combine more kinds of ExtAddrMode fields.

Does it makes sense for you to review it and extend with select support and other than base parts?

I will insist on collaboration here. It doesn't have to be the case that we land either patch as currently structured; we could instead extract common functionality they can both build on. We don't want to waste the time either of you have put into this, and as currently structured the two patches are conflicting. That needs to change.

Sep 25 2017, 5:02 AM

Sep 22 2017

reames added a comment to D36258: Disable loop peeling during full unrolling pass..

That's clearly interesting. This change, however, seems like it should be more-or-less a nop. If you're going to fully unroll, why would peeling help? Do you end up with a shorter critical path through the branches if we "peel" first?

In our pass pipeline, we'd end up with loop-unrolling being quite a bit earlier than upstream. This wasn't so much an intentional choice as an accident of history that we really hadn't evaluated up until now. My best guess is that the peeling was accidentally exposing information to other transformations and that the actual unrolling was incidental to the performance swing. Someone on my team is investigating that a bit further to see what actually happened; what I just said was just an educated guess.

Sep 22 2017, 12:32 PM

Sep 21 2017

reames added a comment to D36258: Disable loop peeling during full unrolling pass..

FYI, this patch causes a somewhat serious regression on one of our internal benchmarks. Given we have a custom pass pipeline, it's definitely our responsibility to adapt to upstream changes not the other way around, but it would have helped us recognize the problem if either of two things had happened along with this patch:

  1. The patch had been separated into two pieces: adding the new control know without changing the default and then a small patch changing the default.
  2. The change had been announced in some way. An email to llvm-dev probably would have been sufficient.
Sep 21 2017, 10:18 PM

Sep 11 2017

reames added a comment to D37463: Fix miscompile in LoopSink pass.

I need to read what C++ specification says about this particular issue, but basically LLVM is not only used to compile C++. This situation can be illegal in other languages (again, need to dig more through specifications). My proposal is to add an option that prohibits this transform and set it to false by default, with abitily to turn it off for languages where it is prohibited.

LLVM has a memory model.
https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations

If this violates LLVM's memory model, it's a bug.
It it doesn't, it should not be turned off, and an other-language frontend needs to make sure the code it generates is correct in LLVM's memory model.
(or of course, start a discussion about changing the memory model)

Strongly agreed with this. Neither the C++ memory model or the Java memory model are directly relevant to this discussion. We should focus on the LLVM memory model exclusively when defining LLVM bugs and revise the LLVM memory model if needed to support one of our frontend languages.

Sep 11 2017, 6:36 PM
reames added a comment to D37460: [GVN] Prevent LoadPRE from hoisting across instructions that don't pass control flow to successors.

We consider volatile loads and stores as potentially trapping as a courtesy to our users. Strictly speaking, it's undefined behavior in C, but people sometimes intentionally trigger SIGSEGV using volatile loads, so we don't want to cause an unrelated crash before that happens. Breaking that testcase should be fine.

I disagree. This would be breaking optimizations *across* a volatile load, not breaking optimizations *of* a volatile load. I think the isGuaranteedTo... scheme is probably the right one, but I think we got our semantics for that function wrong for volatile loads.

Sep 11 2017, 4:17 PM

Sep 10 2017

reames accepted D29937: [RISCV 15/n] Implement lowering of ISD::SELECT.

Reflecting previous LGTM again.

Sep 10 2017, 7:18 PM
reames added a comment to D23566: [RISCV 8/10] Add support for all RV32I instructions.

LGTM w/comments applied before commit.

Sep 10 2017, 7:18 PM
reames accepted D23566: [RISCV 8/10] Add support for all RV32I instructions.
Sep 10 2017, 7:18 PM

Sep 4 2017

reames added a comment to D37418: [X86] Use btc/btr/bts to implement xor/and/or that affects a single bit in the upper 32-bits of a 64-bit operation..

I ran into this case in a snippet of hot code just Friday, so I'm glad to see someone's working on it. :) In the case I had, the register allocator was spilling a register in a hot loop just to free up room for constant. I hadn't had a chance to actually performance test the tweaked assembly, but I'd be very surprised if the btc variant wasn't faster in that case.

Sep 4 2017, 1:46 PM

Aug 29 2017

reames accepted D37209: [LSR] Fix Shadow IV in case of integer overflow.

LGTM

Aug 29 2017, 12:17 AM

Aug 28 2017

reames requested changes to D37227: [SCEV] Ensure ScalarEvolution::createAddRecFromPHIWithCastsImpl is working with an add expression..
Aug 28 2017, 1:32 PM
reames added a comment to D37209: [LSR] Fix Shadow IV in case of integer overflow.

Further comments.

Aug 28 2017, 1:19 PM
reames added a comment to D37209: [LSR] Fix Shadow IV in case of integer overflow.

Hi Max,

I believe, C and C++ standards say that signed integers overflow has undefined behavior.
So in your example we can safely change program behavior in case of overflow.

"If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [...]"
Unsigned case is more complicated.

Thanks,
Evgeny

Evgeny, what the C and C++ standards say is irrelevant to the semantics of LLVM IR and do not come into the discussion at all. It does not effect the legality of the transform in any way.

Aug 28 2017, 9:46 AM
reames requested changes to D37209: [LSR] Fix Shadow IV in case of integer overflow.
Aug 28 2017, 9:31 AM

Aug 25 2017

reames accepted D35380: [RuntimeUnroll] Add heuristic for unrolling multi-exit loop.

LGTM

Aug 25 2017, 4:59 PM
reames accepted D35511: Add element-atomic mem intrinsic canary tests for Thread Sanitizer..
Aug 25 2017, 3:40 PM
reames added a comment to D29937: [RISCV 15/n] Implement lowering of ISD::SELECT.

Much, much cleaner. Thanks!

Aug 25 2017, 8:51 AM

Aug 24 2017

reames requested changes to D29937: [RISCV 15/n] Implement lowering of ISD::SELECT.
Aug 24 2017, 5:24 PM

Aug 22 2017

reames accepted D36975: [InstCombine] Fold branches with irrelevant conditions to a constant.

LGTM

Aug 22 2017, 1:43 PM

Aug 16 2017

reames abandoned D19452: [instcombine] recognize three way comparison idioms.
Aug 16 2017, 3:15 PM
reames accepted D36462: [CGP] Fix the rematerialization of gc.relocates.

LGTM

Aug 16 2017, 10:14 AM

Aug 14 2017

reames requested changes to D36462: [CGP] Fix the rematerialization of gc.relocates.
Aug 14 2017, 11:12 AM

Jul 27 2017

reames added a comment to D35840: All libcalls should be considered to be GC-leaf functions..
In D35840#822809, @anna wrote:

This change looks good to me. However, I would suggest separating out the PlaceSafepoints (and it's testcase) change from the RewriteStatepointsForGC change. We don't use placeSafepoint anymore, so we should perhaps just deprecate it upstream, instead of fixing it.
@reames: What do you suggest?

Fixing both is definitely the right answer for the moment. PlaceSafepoints is questionable. It's a nice proof of concept, but given we aren't using it and thus testing it, it's probably starting to bit rot. I'd lean toward removing it, but let's check on llvm-dev to see if anyone else is using it before we just delete the code.

Jul 27 2017, 9:39 AM

Jul 18 2017

reames requested changes to D35380: [RuntimeUnroll] Add heuristic for unrolling multi-exit loop.
Jul 18 2017, 1:25 PM

Jul 17 2017

reames accepted D35510: Add element-atomic mem intrinsic canary tests for Memory Sanitizer..
Jul 17 2017, 2:33 PM
reames accepted D35507: Add element-atomic mem intrinsic canary tests for Dataflow Sanitizer..

LGTM except that assuming the atomic versions only get used on race-free programs would seem well, odd to say the least.

Jul 17 2017, 2:30 PM
reames accepted D35508: Add element-atomic mem intrinsic canary tests for Efficiency Sanitizer..
Jul 17 2017, 2:18 PM
reames accepted D35505: Add element-atomic mem intrinsic canary tests for Address Sanitizer..

LGTM

Jul 17 2017, 2:05 PM
reames accepted D35502: Add element-atomic mem intrinsic canary tests for InstCombine..

LGTM w/minor comment optional

Jul 17 2017, 2:02 PM
reames updated subscribers of D35502: Add element-atomic mem intrinsic canary tests for InstCombine..
Jul 17 2017, 1:31 PM
reames requested changes to D35502: Add element-atomic mem intrinsic canary tests for InstCombine..

FYI, Daniel and I are talking about this one offline and are going to iterate quickly on testing style. You'll see a couple rounds of updated patches on this within the next few minutes.

Jul 17 2017, 1:30 PM

Jul 11 2017

reames accepted D34885: Add element atomic memset intrinsic.

Unless anyone objects to this, I intend to LGTM this and move forward with the original approach. Any concerns?

LGTM

Jul 11 2017, 2:26 PM

Jul 9 2017

reames added a comment to D34885: Add element atomic memset intrinsic.

Daniel, and I ended up talking about this one a decent amount offline with one of our other non-LLVM compiler folks. Our conclusions was that the more generic fill pattern isn't really any more common in Java than it is in C/C++. The overwhelmingly most important pattern we want to catch is just zero-initialization of a block of memory, (i.e. atomic bzero) which is covered by the current proposal.

Jul 9 2017, 6:13 AM