diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java b/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java
index d555d8874..056bde5fd 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java
@@ -10,6 +10,7 @@ import org.antlr.v4.runtime.*;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -344,6 +345,9 @@ public class AsmFragment {
       return bound;
    }
 
+   /** Cache for fragment files. Maps signature to the parsed file. */
+   private static Map<String, Asm6502Parser.FileContext> fragmentFileCache = new HashMap<>();
+
    /**
     * Generate assembler code for the assembler fragment.
     *
@@ -351,48 +355,50 @@ public class AsmFragment {
     */
    public void generate(AsmProgram asm) {
       String signature = this.getSignature();
-      ClassLoader classLoader = this.getClass().getClassLoader();
-      final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
-      if (fragmentResource == null) {
-         throw new UnknownFragmentException(signature);
+      Asm6502Parser.FileContext fragmentFile = fragmentFileCache.get(signature);
+      if(fragmentFile==null) {
+         ClassLoader classLoader = this.getClass().getClassLoader();
+         final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
+         if (fragmentResource == null) {
+            throw new UnknownFragmentException(signature);
+         }
+
+         try {
+            InputStream fragmentStream = fragmentResource.openStream();
+            Asm6502Lexer lexer = new Asm6502Lexer(CharStreams.fromStream(fragmentStream));
+            Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer));
+            parser.addErrorListener(new BaseErrorListener() {
+               @Override
+               public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+                  throw new RuntimeException("Error parsing fragment fragmentFile " + fragmentResource + "\n - Line: " + line + "\n - Message: " + msg);
+               }
+            });
+            parser.setBuildParseTree(true);
+            fragmentFile = parser.file();
+            fragmentStream.close();
+            fragmentFileCache.put(signature, fragmentFile);
+         } catch (IOException e) {
+            throw new RuntimeException("Error reading code fragment " + fragmentResource);
+         }
       }
 
-      try {
-         InputStream fragmentStream = fragmentResource.openStream();
-         Asm6502Lexer lexer = new Asm6502Lexer(CharStreams.fromStream(fragmentStream));
-         Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer));
-         parser.addErrorListener(new BaseErrorListener() {
-            @Override
-            public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
-               throw new RuntimeException("Error parsing fragment file " + fragmentResource + "\n - Line: " + line + "\n - Message: " + msg);
-            }
-         });
-         parser.setBuildParseTree(true);
-         Asm6502Parser.FileContext file = parser.file();
-         AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(fragmentResource, asm);
-         asmSequenceGenerator.generate(file);
-         fragmentStream.close();
-      } catch (IOException e) {
-         throw new RuntimeException("Error reading code fragment " + fragmentResource);
-      }
+      AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(signature, this, asm);
+      asmSequenceGenerator.generate(fragmentFile);
 
    }
 
-   private class AsmSequenceGenerator extends Asm6502BaseVisitor {
+   private static class AsmSequenceGenerator extends Asm6502BaseVisitor {
 
-      private URL fragmentResource;
+      private String signature;
       private AsmProgram program;
+      private AsmFragment bindings;
 
-      public AsmSequenceGenerator(URL fragmentResource, AsmProgram program) {
-         this.fragmentResource = fragmentResource;
+      public AsmSequenceGenerator(String signature, AsmFragment bindings, AsmProgram program) {
+         this.signature = signature;
+         this.bindings = bindings;
          this.program = program;
       }
 
-      public AsmSequenceGenerator(URL fragmentResource) {
-         this.fragmentResource = fragmentResource;
-         this.program = new AsmProgram();
-      }
-
       public AsmProgram getProgram() {
          return program;
       }
@@ -427,7 +433,7 @@ public class AsmFragment {
          if (instruction != null) {
             program.addLine(instruction);
          } else {
-            throw new RuntimeException("Error parsing ASM fragment line in " + fragmentResource.toString() + "\n - Line: " + ctx.getText());
+            throw new RuntimeException("Error parsing ASM fragment line in dk/camelot64/kickc/asm/fragment/" + signature + ".asm\n - Line: " + ctx.getText());
          }
          return null;
       }
@@ -505,7 +511,7 @@ public class AsmFragment {
       @Override
       public Object visitExprReplace(Asm6502Parser.ExprReplaceContext ctx) {
          String replaceName = ctx.NAME().getSymbol().getText();
-         return AsmFragment.this.getBoundValue(replaceName);
+         return bindings.getBoundValue(replaceName);
       }
    }
 
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUpliftPotentialRegisterAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUpliftPotentialRegisterAnalysis.java
index 956a9aefc..7ceda386d 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUpliftPotentialRegisterAnalysis.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUpliftPotentialRegisterAnalysis.java
@@ -116,7 +116,7 @@ public class Pass3RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
     * @return A set with registers that are clobbered by all different register assignments in the combination
     */
    private Set<RegisterAllocation.Register> findAlwaysClobberedRegisters(ControlFlowBlock block, Statement statement, RegisterCombinationIterator combinations) {
-      Set<RegisterAllocation.Register> alwaysClobbered = new HashSet<>();
+      Set<RegisterAllocation.Register> alwaysClobbered = new LinkedHashSet<>();
       alwaysClobbered.add(RegisterAllocation.getRegisterA());
       alwaysClobbered.add(RegisterAllocation.getRegisterX());
       alwaysClobbered.add(RegisterAllocation.getRegisterY());
diff --git a/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log b/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log
index e42d66534..fb064b3ee 100644
--- a/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log
+++ b/src/main/java/dk/camelot64/kickc/test/ref/bresenham.log
@@ -1171,13 +1171,13 @@ B3_from_B2:
 //SEG31 [6] phi (byte*) cursor#5 = (byte*) cursor#2 -- register_copy 
   jmp B3
 
-Statement [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] always clobbers reg byte y reg byte a 
-Removing always clobbered register reg byte y as potential for zp byte:4 [ x#2 x#1 ]
+Statement [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] always clobbers reg byte a reg byte y 
 Removing always clobbered register reg byte a as potential for zp byte:4 [ x#2 x#1 ]
-Removing always clobbered register reg byte y as potential for zp byte:5 [ e#3 e#5 e#1 e#2 ]
+Removing always clobbered register reg byte y as potential for zp byte:4 [ x#2 x#1 ]
 Removing always clobbered register reg byte a as potential for zp byte:5 [ e#3 e#5 e#1 e#2 ]
-Removing always clobbered register reg byte y as potential for zp byte:6 [ y#2 y#4 y#1 ]
+Removing always clobbered register reg byte y as potential for zp byte:5 [ e#3 e#5 e#1 e#2 ]
 Removing always clobbered register reg byte a as potential for zp byte:6 [ y#2 y#4 y#1 ]
+Removing always clobbered register reg byte y as potential for zp byte:6 [ y#2 y#4 y#1 ]
 Statement [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ x#1 e#1 cursor#1 y#2 ] always clobbers reg byte a 
 Statement [9] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ x#1 e#1 cursor#2 y#1 ] always clobbers reg byte a 
 Statement [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] always clobbers reg byte a 
diff --git a/src/main/java/dk/camelot64/kickc/test/ref/ptrtest.log b/src/main/java/dk/camelot64/kickc/test/ref/ptrtest.log
index 6229f55ba..79baf5b71 100644
--- a/src/main/java/dk/camelot64/kickc/test/ref/ptrtest.log
+++ b/src/main/java/dk/camelot64/kickc/test/ref/ptrtest.log
@@ -2066,9 +2066,9 @@ lvalue__B1_from_B2:
 //SEG70 [27] phi (byte) lvalue::i#2 = (byte) lvalue::i#1 -- register_copy 
   jmp lvalue__B1
 
-Statement [9] *((byte*) lvaluevar::screen#2) ← (byte) 4 [ lvaluevar::i#2 lvaluevar::screen#2 ] always clobbers reg byte y reg byte a 
-Removing always clobbered register reg byte y as potential for zp byte:2 [ lvaluevar::i#2 lvaluevar::i#1 ]
+Statement [9] *((byte*) lvaluevar::screen#2) ← (byte) 4 [ lvaluevar::i#2 lvaluevar::screen#2 ] always clobbers reg byte a reg byte y 
 Removing always clobbered register reg byte a as potential for zp byte:2 [ lvaluevar::i#2 lvaluevar::i#1 ]
+Removing always clobbered register reg byte y as potential for zp byte:2 [ lvaluevar::i#2 lvaluevar::i#1 ]
 Statement [15] (byte) rvaluevar::b#0 ← * (byte*) rvaluevar::screen#2 [ rvaluevar::i#2 rvaluevar::screen#2 ] always clobbers reg byte a reg byte y 
 Removing always clobbered register reg byte a as potential for zp byte:5 [ rvaluevar::i#2 rvaluevar::i#1 ]
 Removing always clobbered register reg byte y as potential for zp byte:5 [ rvaluevar::i#2 rvaluevar::i#1 ]