diff --git a/src/pl-attvar.c b/src/pl-attvar.c
index c611e932c..a08b00f13 100644
--- a/src/pl-attvar.c
+++ b/src/pl-attvar.c
@@ -190,6 +190,17 @@ assignAttVar(Word av, Word value ARG_LD)
   a = valPAttVar(*av);
   registerWakeup(a, value PASS_LD);
 
+ /* When first attribute is $VAR$ skip binding (allows to be done elsewhere) */
+  { Word l = a;
+        deRef(l);
+        if ( isTerm(*l) )
+         { Functor f = valueTerm(*l);
+          if ( f->definition == FUNCTOR_att3 )
+          { Word n;
+                deRef2(&f->arguments[0], n);
+                if ( *n == ATOM_dvard ) return;
+        }}}
+
   TrailAssignment(av);
   if ( isAttVar(*value) )
   { DEBUG(1, Sdprintf("Unifying two attvars\n"));
@@ -597,6 +608,32 @@ restoreWakeup(wakeup_state *state ARG_LD)
 }
 
 
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ attv_bind(+AttVar, +Value) is det.
+    Binds AttVar with Value without calling wakeup
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+static
+PRED_IMPL("attv_bind", 2, attv_bind, 0)
+{ PRED_LD
+  Word av;
+
+  if ( !hasGlobalSpace(0) )
+  { int rc;
+    if ( (rc=ensureGlobalSpace(0, ALLOW_GC)) != TRUE )
+      return raiseStackOverflow(rc);
+  }
+
+  deRef2(valTermRef(A1), av);
+  if (!isAttVar(*av) )
+  { return PL_error("attv_bind", 2, NULL, ERR_UNINSTANTIATION, 1, A1);
+ }
+
+ TrailAssignment(av);
+  *av = linkValI(valTermRef(A2));
+  return TRUE;
+}
+
 		 /*******************************
 		 *	     PREDICATES		*
 		 *******************************/
@@ -1400,6 +1437,7 @@ BeginPredDefs(attvar)
   PRED_DEF("del_attr",  2, del_attr2, 0)
   PRED_DEF("del_attrs", 1, del_attrs, 0)
   PRED_DEF("get_attrs", 2, get_attrs, 0)
+  PRED_DEF("attv_bind", 2, attv_bind, 0)
   PRED_DEF("put_attrs", 2, put_attrs, 0)
   PRED_DEF("$freeze",   2, freeze,    0)
   PRED_DEF("$eval_when_condition", 2, eval_when_condition, 0)