[llvm-dev] IR canonicalization: select or bool math?

Sanjoy Das via llvm-dev llvm-dev at lists.llvm.org
Wed Sep 28 22:12:43 PDT 2016


My gut tells me that Hal is right, and we should prefer zexts as long
as the select boils down to one instruction, but let me go against my
intuition and try to list two reasons why we should prefer selects:

  * Folding operations into selects: it is trivial to transform
    f(select X, Const0, Const1) to select X, f(Const0), f(Const1),
    while doing that can be difficult for zexts.

    define i32 @sel_1_or_0(i1 %a) {
      %b = select i1 %a, i32 1, i32 0
      %k = add i32 %b, 50
      ret i32 %k
    }

    ==>

    define i32 @sel_1_or_0(i1 %a) {
      %b = select i1 %a, i32 51, i32 50
      ret i32 %b
    }

    but

    define i32 @sel_1_or_0(i1 %a) {
      %b = zext i1 %a to i32
      %k = add i32 %b, 50
      ret i32 %k
    }

    is not as natural to transform.

  * zexts (resp. sexts) lose information when combined with nuw
    (resp. nsw) operations.

    That is, if we inline

    define i32 @sel_1_or_0(i1 %a) {
      %b = zext i1 %a to i32
      ret i32 %b
    }

    into f and get

    define i32 @f(i32 %x, i32 %y) {
      %x.zext = ...
      %y.zext = ...
      ;; There are some existing use of %x.zext and %y.zext
      %a = add nuw i1 %x, %y
      %b = zext i1 %a to i32
      ret i32 %b
    }

    then we'll get (following your instructions, I've not verified that
    this actually happens :) )

    define i32 @f(i1 %x, i1 %y) {
      %x.zext = ...
      %y.zext = ...
      %a = add nuw i32 %x.zext, %y.zext
      ret i32 %a
    }

    but we've now lost information -- we no longer know that %a is 0 or
    1 -- it can also be 2.  This would not happen if we always
    canonicalized zext i1 C to iN to select C, iN 1, iN 0

-- Sanjoy


More information about the llvm-dev mailing list