I wrote a peephole optimizer for QBE
&gt; Notably, O will fail to optimize this:<p><pre><code>          movl �x, �x
          movl �x, �i
          movl �i, �x
          movq %r12, %rdi
</code></pre>
Easily handled by TXR:<p><pre><code>  $ txr opt.txr data
          movl �x, �x
          movl �x, �i
          movq %r12, %rdi

  $ cat opt.txr 
  @(repeat)
  @  (cases)@; eliminate wasteful reverse move
          movl @x, @y
          movl @y, @x
  @    (output)
          movl @x, @y
  @    (end)
  @  (or)@; fallback: output one line, advance by one line
  @    line
  @    (do (put-line line))
  @  (end)
  @(end)
</code></pre>
The setup here is not general, because we want to iterate on the pattern matching; not just match a pattern, consume that part of the input, transform it, and move on.<p>The transformed output has to be pushed back into the input. (Iterating the tool on the entire file to a fixed point is possible, but inefficient.)<p>In the TXR Lisp compiler (which does this kind of optimizing on List structures, not text), I wrote a little macro called <i>rewrite-case</i> for this: this repeatedly applies multiple pattern matching to the start of a list, rewriting the matched part of the list. When a fixed point is reached, it then deposits one item to the output list, and marches down by one item.<p><a href="https:&#x2F;&#x2F;www.kylheku.com&#x2F;cgit&#x2F;txr&#x2F;tree&#x2F;stdlib&#x2F;optimize.tl?h=txr-274#n116" rel="nofollow">https:&#x2F;&#x2F;www.kylheku.com&#x2F;cgit&#x2F;txr&#x2F;tree&#x2F;stdlib&#x2F;optimize.tl?h=t...</a><p>&gt; It would be better if we printed out just the first line after discovering that the first three lines do not satisfy any optimization patterns, then check lines two through four for any optimization patterns; if we did that, we could optimize the last three lines.<p>That&#x27;s an absolute requirement; if no patterns match, the peephole must move by one instruction.<p>It&#x27;s exactly like a lexical analyzer throwing away one character if it doesn&#x27;t match any token. (Lex will do that by default and print the character to standard output.)<p>&gt; <i>Interestingly, we cannot actually say with certainty if moving %rdi into %r12 and back again is useless.</i><p>Well, yes; peephole optimization is generally done on basic blocks, not on entire programs.<p>You can peephole a program containing jump labels, but you have to make sure your patterns do not blindly match across them.<p>For instance, say we want to peephole out this wasteful register reverse move, but one instruction away:<p><pre><code>  $ cat data2
          movl �x, �x
          movl �x, �i
          xorl %esi, �x
          movl �i, �x
          movq %r12, %rdi

  $ cat data3
          movl �x, �x
          movl �x, �i
  label:
          xorl %esi, �x
          movl �i, �x
          movq %r12, %rdi
</code></pre>
We can peephole it for data2, but not data3.<p><pre><code>  $ txr opt.txr data2
          movl �x, �x
          movl �x, �i
          xorl %esi, �x
          movq %r12, %rdi
  $ txr opt.txr data3
          movl �x, �x
          movl �x, �i
  label:
          xorl %esi, �x
          movl �i, �x
          movq %r12, %rdi

</code></pre>
How I did it was by adding a pattern match for a generic two-opcode instruction in between the two, and doing some checks on the register:<p><pre><code>  @(repeat)
  @  (cases)@; eliminate wasteful reverse move
          movl @x, @y
          movl @y, @x
  @    (output)
          movl @x, @y
  @    (end)
  @  (or) @; like above, but with unrelated insn in between
          movl @x, @y
          @opc @a, @b
          movl @y, @x
  @    (require (nequal a x))
  @    (output)
          movl @x, @y
          @opc @a, @b
  @    (end)
  @  (or)@; fallback: output one line
  @    else
  @    (do (put-line else))
  @  (end)
  @(end)
</code></pre>
Here we add the <i>require</i> constraint that the destination operand of the unrelated instruction cannot be clobbering the destination of the first movl.<p>This will be subtly wrong if there are assembly language instructions which move data in the opposite direction.<p>We could add a<p><pre><code>   @(require (memqual opc &#x27;(&quot;movl&quot; &quot;foo&quot; &quot;bar ...))
</code></pre>
i.e. constrain to a specific set of instructions that we can match over.