The eight-time Swiss champion won 7-6(3), 1-6, 6-3, 6-4 in a titanic contest lasting three hours, two minutes.
Federer took the first set with a tie-break, winning the final four points in succession. Nadal responded impressively breaking Federer twice to take the second set 6-1 in 37 minutes.
Federer, however, regained his poise and form, playing high quality tennis to take the third set and move to 5-3 in the fourth.
Nadal saved two match points on his own serve at 3-5 but could not force home a break point at 4-5. Another two match points came, and went, but at the fifth attempt Federer clinched the match.
“I’m exhausted,” said Federer. “It was tough at the end – Rafa played some unbelievable shots to stay in the match.”
Federer meets Novak Djokovicin the final, a repeat of the finals of 2014 and 2015 both of which were won by Djokovic.