When it comes to adding or updating your own data when a post is saved, I agree with Subrata. But if you wish to alter post data before it is added or updated, “wp_insert_post_data” can be great for that. It’s not well named as it fires on almost any post change action (excluding attachments), not just new insertions. The very first insertion is signified by $postarr[‘ID’] being assigned 0 as a value, but that’s likely to be an automatic internal insertion to establish an ID when there is still no user data in the post, the first “draft” post.
By the time the user publishes or otherwise saves the post, the ID is already established. The only time it’s 0 and the other data is available is when the post is added via script and not through the post edit screen. Thus the “wp_insert_post_data” filter is not suitable if you need to really know the update status. In such cases, you may do as Subrata suggests where the $update status is one of the passed parameters. If you need to re-save post data from “save_post”, take measures to avoid an infinite loop situation.
There are also various post transition actions that only fire under certain post status changes. For example, the “draft_to_publish” action only fires for first published posts and “publish_to_publish” only fires for updates.