You've nailed it, thank you!
Finally I'm understanding what's going on.
I wasn't paying attention to the fact that generate_series really expects for timezone inputs. So when I was passing the upper bound as '2014-10-20'::DATE, the value was being cast to 2014-10-20 00:00:00-02.
postgres=# SELECT '2014-10-20'::TIMESTAMPTZ;
timestamptz
------------------------
2014-10-20 00:00:00-02
(1 row)
But after the DST change the generate_series changes the hour in the generated values as in 2014-10-20 01:00:00-02, which is bigger than 2014-10-20 00:00:00-02 and because of that it's not returned.
Using a larger upper bound solved my problem.
postgres=# SELECT generate_series('2014-10-15 00:00:00'::TIMESTAMPTZ, '2014-10-20 23:59:59'::TIMESTAMPTZ, '1 DAY'::INTERVAL);
generate_series
------------------------
2014-10-15 00:00:00-03
2014-10-16 00:00:00-03
2014-10-17 00:00:00-03
2014-10-18 00:00:00-03
2014-10-19 01:00:00-02
2014-10-20 01:00:00-02
(6 rows)
Thank you again!
Sérgio Saquetim