A practical multi-word compare-and-swap operation
In a concurrent runtime environment simple things can seem weird ... hope this can help.

We have a BUILT-IN ATOMIC CAS1 having this semantic:

int CAS1(int *addr, int oldval, int newval) {
  int currval = *addr;
  if (currval == oldval) *addr = newval;
  return currval;
}


We need to define an ATOMIC RDCSS function using CAS1 and having the following semantic:

int RDCSS(int *addr1, int oldval1, int *addr2, int oldval2, int newval2) {
  int res = *addr;
  if (res == oldval2 &amp;&amp; *addr1 == oldval1) *addr2 = newval2;
  return res;
}


Intuitively: we need to CONCURRENTLY change the value at addr2 only if *addr1 == oldval1 ... if another thread is changing it we can help the other thread to complete the operation, then we can retry.

RDCSS function will be used (see article) to define CASN. Now, we define a RDCSS Descriptor in the following way:

RDCSSDESCRI
int *addr1   
int oldval1
int *addr2   
int oldval2
int newval2


Then we implement RDCSS in the following way:

int RDCSS( RDCSSDESCRI *d ) {
  do {
    res = CAS1(d-&gt;addr2, d-&gt;oldval2, d);  // STEP1
    if (IsDescriptor(res)) Complete(res); // STEP2
  } while (IsDescriptor(res);             // STEP3
  if (res == d-&gt;oldval2) Complete(d);     // STEP4
  return res;
}

void Complete( RDCSSDESCRI *d ) {
  int val = *(d-&gt;addr1);
  if (val == d-&gt;oldval1) CAS1(d-&gt;addr2, d, d-&gt;newval2);
    else CAS1(d-&gt;addr2, d, d-&gt;oldval2);  
}



STEP1: first we try to change the value of *addr2 to our (own) descriptor d, if CAS1 succeeds then res == d->oldval2 (i.e. res is NOT a descriptor)
STEP2: check if res is a descriptor i.e. STEP1 failed (another thread changed addr2) ... help another thread completing the operation
STEP3: retry the STEP1 if we didn't succeed in storing our descriptor d
STEP4: if we fetched our expected value from addr2 then we succeeded in storing our descriptor (pointer) in addr2 and we can complete our task storing newval2 to *addr2 iif *addr1 == oldval1


ANSWER TO YOUR QUESTION

If we omit STEP4 then the if(... &amp;&amp; *addr1==oldval1) *addr2=newval2 part of the RDCSS semantic will never be executed (... or better: it can be executed in an umpredictable way by other threads helping the current one).

As pointed out by you in your comment the condition if(res == d1->oldval2) at STEP4 is unnecessary: even if we omit it, both CAS1 in Complete() will fail because *(d->addr2)!=d. Its only purpouse is avoid a function call.

Example T1=thread1, T2=thread2:

remember that addr1 / addr2 are in a shared data zone !!!

T1 enter RDCSS function
T2 enter RDCSS function
T2 complete STEP1 (and store the pointer to its descriptor d2 in addr2)
T1 at STEP1 the CAS1 fails and res = d2
T2 or T1 completes *(d2-&gt;addr2)=d2-&gt;newval2 (suppose that *(d2-&gt;addr1)==d2-&gt;oldval1)
T1 execute STEP1 and now CAS1 can fail because *addr2 == d2-&gt;newval2
   and maybe d2-&gt;newval2 != d1-&gt;oldval2, in every case at the end 
   res == d2-&gt;newval2 (fail) or
   res == d1-&gt;oldval2 (success)
T1 at STEP2 skips the call to Complete() (because now res is not a descriptor)
T1 at STEP3 exits the loop (because now res is not a descriptor)
T1 at STEP4 T1 is ready to store d1-&gt;newval2 to addr2, but only if
   *(d1-&gt;addr2)==d (we are working on our descriptor) and *(d1-&gt;addr1)==d1-&gt;oldval1
   ( Custom() function)