/*
after dusk passed,
there is a starry sky.
*/
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define m_k make_pair
#define mod 1000000007
#define int long long
#define len(a) (int)a.size()
using namespace std;
const int N=1e6+100;
int n,m,cnt,dfn[N],low[N],col[N],w,g[N],z[N],father[N];
int dp[N][2],sz[N];
bool br[N];
pair<int,int> ed[N];
vector <int> e[N];
int tot,first[N],nxt[N*2],point[N*2],id[N*2];
inline void add(int &a,int b){a=((a+b>=mod)?a+b-mod:a+b);}
inline void del(int &a,int b){a=((a-b<0)?a-b+mod:a-b);}
inline void mul(int &a,int b){a=a*b%mod;}
inline int m_pow(int a,int b)
{
	int ans=1;
	while (b)
	{
		if (b&1) mul(ans,a);
		b>>=1;
		mul(a,a);
	}
	return ans;
}
inline int read()
{
	int f=1,x=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return x*f;
}
inline void add_edge(int x,int y,int z)
{
	nxt[++tot]=first[x],first[x]=tot;
	point[tot]=y,id[tot]=z;
}
void dfs(int x,int in)
{
	dfn[x]=low[x]=++cnt;
	for (int i=first[x];i!=-1;i=nxt[i]) if (id[i]!=in)
	{
		int u=point[i];
		if (!dfn[u])
		{
			dfs(u,id[i]);
			low[x]=min(low[x],low[u]);
			if (low[u]>dfn[x]) br[id[i]]=1;
		}
		else low[x]=min(low[x],dfn[u]);
	}
}
void dfs1(int x)
{
	col[x]=w;
	for (int i=first[x];i!=-1;i=nxt[i]) if (!br[id[i]])
	{
		int u=point[i];
		if (!col[u]) dfs1(u);
	}
}
namespace tree
{
	void dfs(int x,int fa)
	{
		father[x]=fa;sz[x]=1;
		for (int u:e[x]) if (u!=fa)
		{
			dfs(u,x);
			sz[x]+=sz[u];
		}
		dp[x][1]=z[g[x]]-1;dp[x][0]=1;
		for (int u:e[x]) if (u!=fa)
		{
			int f[2];f[0]=f[1]=0;
			add(f[0],dp[x][0]*dp[u][0]*2%mod);
			add(f[1],dp[x][0]*dp[u][1]%mod);
			add(f[1],dp[x][1]*dp[u][0]*2%mod);
			add(f[1],dp[x][1]*dp[u][1]%mod);
			dp[x][0]=f[0];dp[x][1]=f[1];
		}
	}
	int solve()
	{
		dfs(1,1);
		int ans=0;
		for (int x=1;x<=w;x++)
		{
			int tmp=1;
			for (int u:e[x]) if (u!=father[x]) mul(tmp,dp[u][0]*2+dp[u][1]);
			add(ans,tmp*(z[g[x]]-1)%mod*z[w-sz[x]]%mod);
			int f[3],g[3];
			memset(f,0,sizeof(f));
			f[0]=1;
			for (int u:e[x]) if (u!=father[x])
			{
				memset(g,0,sizeof(g));
				for (int i=0;i<3;i++)
				{
					add(g[i],f[i]*dp[u][0]*2%mod);
					add(g[min(2ll,i+1)],f[i]*dp[u][1]%mod);
				}
				memcpy(f,g,sizeof(f));
			}
			add(ans,f[2]*z[w-sz[x]]%mod);
		}
		mul(ans,z[m-w+1]);
		return ans;
	}
}
signed main()
{
	// freopen("barrack.in","r",stdin);
	// freopen("barrack.out","w",stdout);
	tot=-1;
	memset(first,-1,sizeof(first));
	n=read();m=read();
	for (int i=1;i<=m;i++)
	{
		int u=read(),v=read();
		ed[i]=m_k(u,v);
		add_edge(u,v,i);add_edge(v,u,i);
	}
	dfs(1,-1);
	w=0;
	for (int i=1;i<=n;i++) if (!col[i])
	{
		w++;
		dfs1(i);
	}
	for (int i=1;i<=n;i++) g[col[i]]++;
	for (int i=1;i<=m;i++) if (br[i])
	{
		int u=ed[i].first,v=ed[i].second;
		u=col[u];v=col[v];
		e[u].push_back(v);e[v].push_back(u);
	}
	z[0]=1;
	for (int i=1;i<=max(n,m);i++) z[i]=z[i-1]*2%mod;
	printf("%lld\n",tree::solve());
}