Apex Code is single-threaded. This means that your code runs sequentially, from top to bottom, until the end of the method. If you have validation occurring first, followed by other updates, your code will run to its end. Once it ends, if any records received an error (via addError), and allOrNone is "false", then those records are set aside, any work done is rolled back, and another attempt is made.
You can optimize your code by skipping any other updates when addError has already been used, because it'll either roll back the entire transaction anyways (allOrNone=true), or it'll cause the transaction to run twice (allOrNone=false). You should not perform any other work alongside validation rules as a matter of performance.
Realistically, that means you should write your trigger in a similar pattern:
if(TriggerHandlerClass.validatedRecords(Trigger.new)) {
TriggerHandlerClass.processRecords(Trigger.new));
}
This will allow partial updates to run at an optimal speed.