In a modern instruction set like x86-64 there are many many many ways to accomplish the same task using a series of old simple instructions all the way up to the complex SIMD instructions. If one wanted to determine the semantic equivalence of a series of instructions, could this be done rationally or must it only be done experimentally?

For the sake of simplicity I am restricting the number of instructions in a series to something like ten.

The naive way to solve the problem would be to generate all of the potential inputs and experimentally check the results.

A slightly smarter way might be to determine the edges of the input states and only test those.

But I'm wondering if there's a way to represent each of the assembly instructions (and series of instructions) as a data structure that could be compared. Is this a tractable problem? Or is this clearly something like the halting problem?

Intuitively this feels like something similar to what happens inside a compiler.

  • 1
    $\begingroup$ You might be interested in the idea of "supercompilation", where the optimizer pass works by searching for an equivalent sequence of instructions that is more efficient. There's research literature on how to do that (e.g., SAT/SMT, random testing, theorem proving, and more). $\endgroup$
    – D.W.
    Mar 29 '18 at 19:32
  • $\begingroup$ Thank you. I found a bunch of interesting papers on super compilation. Looks fascinating. $\endgroup$
    – guidoism
    Mar 29 '18 at 19:57

If you restrict to programs of some fixed, finite length then yes, this is decidable. There are only a finite number of possible programs so there is a finite list of which ones are equivalent to one another. A program that is hard-coded with that list can answer the question just by looking up the two programs.

However, if you don't restrict the length of the programs, the problem becomes undecidable: if it were decidable, you could solve the halting problem ("Does program $P$ halt with input $I$?") by rephrasing it as "Is the program that simulates $P$ running on input $I$ equivalent to this trivial program that always halts?"

As an aside, why do you feel that a compiler would need to do this? Compilers just take a program represented in one form (source code) and translate it into another form (the executable image). The translation process guarantees that the two are semantically equivalent, so there's no need to check.

  • 1
    $\begingroup$ I agree with all of the above, but I'd like to observe that for the problem to be undecidable we need both unbounded program length and unbounded memory. Under the assumption of bounded memory, we can decide trace equivalence by checking whether the two transition monoids are isomorphic (with, for example, Hopcroft's algorithm). $\endgroup$
    – quicksort
    Mar 29 '18 at 17:21
  • $\begingroup$ Thanks for the answer. I don't actually need a compiler to do this. It's all just curiosity while exploring parts of CS that in the past I've never had time to touch. I'm playing around with x64 SIMD instructions and was curious if there was an existing method to describe what each one does more formally than the Intel manuals. Honestly, what would be cool would be to know the microcode for each, but I know that's just a dream. $\endgroup$
    – guidoism
    Mar 29 '18 at 19:43
  • $\begingroup$ How are we making that "finite list"? There is a Turing machine with a few thousand states that halts if and only if SRP, an extension of ZFC, is inconsistent. (Some finite machine could be made for ZFC.) Therefore, SRP can't prove whether that program is equivalent to an obviously non-terminating program unless SRP is inconsistent. Basically, for a given program size there is some finite amount of advice that solves the problem, but beyond a certain size I can no longer convince you that that advice is "right". $\endgroup$ Mar 29 '18 at 23:53
  • $\begingroup$ @DerekElkins It's finite, so it's decidable. Neither of us could write the program that decides it, but decidability isn't amount my ability or yours. $\endgroup$ Mar 29 '18 at 23:55
  • $\begingroup$ @DavidRicherby I didn't say it was undecidable, but I think the answer is a bit misleading to the OP. Basically, there is a Turing machine that can correctly compute the result, but even if I gave it to you, you couldn't convince yourself that it is correct. The OP isn't just asking whether the problem is decidable in the theoretical sense. In your defense though, the problem is completely intractable, practically speaking, before this theoretical issue comes up. $\endgroup$ Mar 30 '18 at 0:01

In the real world you can't.

Sure, you could simply run both sequences on a simulator, and compare the final states to see if they are identical.

Complications are; you can't tell in advance that either of the sequences will ever finish (halting problem). Hidden state in the processor (caches, interrupts, etc. see meltdown and spectre) can alter the outcome. Real programs have inputs and produce different outputs depending; it's tough to test all possible inputs.

  • 1
    $\begingroup$ This doesn't work, because the final state might depend on the initial state. Two code sequences are considered equivalent only if they lead to the same final state if started from the same initial state -- and this has to hold for all initial states. Exhaustively enumerating all possible initial states is not feasible. $\endgroup$
    – D.W.
    Mar 30 '18 at 18:35
  • $\begingroup$ You're correct; that would be another complication worth mentioning. $\endgroup$
    – ddyer
    Mar 30 '18 at 20:32
  • $\begingroup$ Since your conclusion is that you cannot, it is misleading to start by saying you can. $\endgroup$
    – PJTraill
    Mar 30 '18 at 21:50
  • $\begingroup$ point taken. rewritten. $\endgroup$
    – ddyer
    Mar 30 '18 at 21:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.