difficulting matching i64 subtract immediate due to isel normalization of sub -> add


For some 64-bit immediates, ARM can generate a two instruction sequence. For example, for the following code:

; 734439407618 = 0x000000ab00000002
define i64 @f1(i64 %a) {
     %tmp = sub i64 %a, 734439407618
     ret i64 %tmp

We should be able to generate:

  subs r0, r0, #1
  sbc r1, r1, #171 @ 0xab

But instead we get:

$ llvm-as < %s | llc -march=thumb -mattr=+thumb2

  mvn r2, #1
  mvn r3, #171
  adds r0, r0, r2
  adc r1, r1, r3

(mvn is "move not").

We have code selector patterns for sube and subc that do the right thing, but they are not used because isel is converting the "sub i64 a, i" into "add i64 a, -i". This leads to the attached DAG that is impossible to write a pattern for because the addc is producing both a carry and a register output, and the adde is consuming the carry and producing another output.

I suppose I can write code to match this... but is there a better way?


dag.tiff (52.8 KB)

You can write a custom expander for legalizetypes of "add i64" that would handle this case and fall through to the normal legalize code in other cases.