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

Sanjay Patel via llvm-dev llvm-dev at lists.llvm.org
Wed Sep 28 15:39:38 PDT 2016

```I have another round of questions about IR select canonicalizations. For
the purity of this quiz, please disregard prior knowledge of how this is
handled by instcombine or how this is lowered by your favorite target...of
course we'll fix it. :) Some answers in the links below if you do want to
know.

Which, if any, of these is canonical?

1. Is a zext simpler than a select?
a. define i32 @sel_1_or_0(i1 %a) {
%b = select i1 %a, i32 1, i32 0
ret i32 %b
}

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

2. What if we have to 'not' the bool?
a. define i32 @sel_0_or_1(i1 %a) {
%b = select i1 %a, i32 0, i32 1
ret i32 %b
}

b. define i32 @sel_0_or_1(i1 %a) {
%not.a = xor i1 %a, true
%b = zext i1 %not.a to i32
ret i32 %b
}

3. Is sext handled differently?
a. define i32 @sel_-1_or_0(i1 %a) {
%b = select i1 %a, i32 -1, i32 0
ret i32 %b
}

b. define i32 @sel_-1_or_0(i1 %a) {
%b = sext i1 %a to i32
ret i32 %b
}

4. What if the sext needs a 'not'?
a. define i32 @sel_0_or_-1(i1 %a) {
%b = select i1 %a, i32 0, i32 -1
ret i32 %b
}

b. define i32 @sel_0_or_-1(i1 %a) {
%not.a = xor i1 %a, true
%b = sext i1 %not.a to i32
ret i32 %b
}

5. What if both constants are non-zero? Ie, the implicit add/sub of the
earlier cases can't be eliminated.
a. define i32 @sel_2_or_1(i1 %a) {
%b = select i1 %a, i32 2, i32 1
ret i32 %b
}

b. define i32 @sel_2_or_1(i1 %a) {
%b = zext i1 to i32 %a
%c = add i32 %b, 1
ret i32 %b
}

6. Does 'sub' make a difference?
a. define i32 @sel_1_or_2(i1 %a) {
%b = select i1 %a, i32 1, i32 2
ret i32 %b
}

b. define i32 @sel_1_or_2(i1 %a) {
%b = zext i1 %a to i32
%c = sub i32 2, %b
ret i32 %c
}

7. Choose between integers that are not consecutive?
a. define i32 @sel_0_or_2(i1 %a) {
%sel = select i1 %a, i32 2, i32 0
ret i32 %sel2
}

b. define i32 @sel_0_or_2(i1 %a) {
%zexta = zext i1 %a to i32
}

8. Choose {0,1,2} based on 2 bools?
a. define i32 @sel_sel(i1 %a, i1 %b) {
%zexta = zext i1 %a to i32
%sel1 = select i1 %a, i32 2, i32 1
%sel2 = select i1 %b, i32 %sel1, %zexta
ret i32 %sel2
}

b. define i32 @sel_sel(i1 %a, i1 %b) {
%zexta = zext i1 %a to i32
%zextb = zext i1 %b to i32