I've used both ICEfaces and PrimeFaces and prefer PrimeFaces for two main reasons: development efficiency and UI performance/responsiveness.
The dialog component illustrates both:
Compare this in PrimeFaces:
<p:dialog widgetVar="dialog"> [content] </p:dialog>
...
<a href="#" onClick="dialog.show()">Open dialog</a>
To this in ICEfaces:
<ice:panelPopup rendered="#{bean.dialogOpen}"> **dialog chrome** [content]
</ice:panelPopup>
<ice:commandLink action="#{bean.showDialog}">Open dialog</ice:commandLink>
In ICEfaces, you need a server-side round trip and a managed bean property + action listener to open a dialog. In PrimeFaces, thanks to "widgetVar", you can bind the component to a client-side variable accessible in jQuery and regular DHTML events.
Further, the PrimeFaces components handle many of the common cases with less code; for example, a dialog component includes the title bar and the "X" to close, while in ICEfaces you have to roll your own for that (or buy the EE with composite components).
Lastly, the "automatic AJAX" server-side DOM diff in ICEfaces can create performance issues server-side if your pages get big - most of the time you know what you want to refresh, and explicitly specifying update="id" on a component is more effective.