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?
- 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
}
- 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
}
- 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
}
- 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
}
- 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
}
- 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
}
- 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
%add = add i32 %zexta, %zexta
ret i32 %add
}
- 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
%add = add i32 %zexta, %zextb
ret i32 %add
}
Links for reference:
https://llvm.org/bugs/show_bug.cgi?id=30273
https://llvm.org/bugs/show_bug.cgi?id=30327
https://reviews.llvm.org/D24480