The following snippet steals the regular C-x C-s to automatically perltidy as well. I added a different definition for perltidy-whole-buffer so that the input point is restored to be somewhere near where it was originally. I also added a check to see if the buffer has been modifed before calling out to perltidy.
(add-to-list 'cperl-mode-hook (lambda () (substitute-key-definition 's
+ave-buffer 'cperl-save-buffer cperl-mode-map global-map)))
(defun cperl-save-buffer (&optional args)
(interactive "p")
(if (buffer-modified-p)
(perltidy-buffer))
(save-buffer t))
(defun perltidy-buffer ()
(interactive)
(let ((orig-point (point)))
(shell-command-on-region
(point-min) (point-max)
"perltidy -st" nil t shell-command-default-error-buffer)
(goto-char (if (<= orig-point (point-max))
orig-point
(point-max)))))