In this particular case, XST should not have trimmed the internal signals and connected the output to GND. This is definitely an issue with XST and a CR has been filed to fix this problem.
Work-around: Adding the KEEP attribute on the internal signal reg_dx fixes this logic trimming.
The same sample code with the work-around is as follows:
entity bug_demo is
Port ( Ext_In : in STD_LOGIC;
Ext_Out : out STD_LOGIC;
clk : in STD_LOGIC);
end bug_demo;
architecture Behavioral of bug_demo is
attribute KEEP : string;
signal sreg : std_logic_vector(0 to 1);
signal reg_dx : std_logic_vector(0 to 1);
attribute KEEP of reg_dx :signal is "TRUE";
begin
Ext_Out <= reg_dx(1);
reg_dx <= sreg;
process(clk)
begin
if clk'event and clk = '1' then
sreg <= Ext_In & sreg(0);
end if;
end process;
end Behavioral;