<html>Hello,<br /><br />I am developing GlobalISel for MIPS. I have a few questions and observations about defining legality of generic instruction and also possible combining of instructions and artifacts in pre/post legalizer combiner or elsewhere (e.g. in some sort of instruction-select patterns).<br /><br />I look at legality as "If generic instruction can be selected into machine instruction, it is legal".<br /><br />For example, let's look at G_ICMP and G_SELECT. In llvm IR type of result of icmp is always i1, and test argument (type 1) in select is also i1.<br />Here is an .ll example:<br /><br />define i32 @f(i32 %a, i32 %b, i32 %c, i32 %d) {<br />entry:<br /> %cmp = icmp slt i32 %a, %b<br /> %cond = select i1 %cmp, i32 %d, i32 %c<br /> ret i32 %cond<br />}<br /><br />and corresponding MIR snippet:<br /><br /> %4:_(s1) = G_ICMP intpred(sgt), %0(s32), %1<br /> %5:_(s32) = G_SELECT %4(s1), %2, %3<br /><br />On mips 32, integer compare uses i32 as result and that result is zero extended.<br />For G_SELECT, we will select instructions that check whether "test register" was zero or not (selected instructions are movz or movn).<br />Test register has size 32, having that in mind, idealy, legalizer should produce<br /><br /> %4:_(s32) = G_ICMP intpred(sgt), %0(s32), %1<br /> %5:_(s32) = G_SELECT %4(s32), %2, %3<br /><br />after combining all extends and truncs.<br /><br />Currently, it is not possible to widen test register (type 1) in G_SELECT and we could end up with telling legalizer that test argument is legal for i1, and later select that register as i32 regardless. Therefore, the question is:<br /><br />Q: What are the plans:<br />a) Is it planned for legalizer to set sizes of all arguments to appropriate sizes of phisical registers (i.e. types s1, s8 and s16 should be widened to s32)?<br />b) Is the plan to sometimes let s1 as legal type and ignore it later?<br />c) Is the plan to sometimes let s1 as legal type and use this type as a hint to select between multiple available instructions using some patterns?<br /><br />For example, in https://reviews.llvm.org/D51489, G_ICMP got its result (type0) legalized as legal for s32 (corresponding to plan a)). We would get similar final output (also correct) if we said that type0 is legal for s1 (corresponding to b), but in this case it is also necessary to: tell that extends are legal for {s32, s1}, regbankselct and instruction select G_ZEXT.<br /><br />It would be nice to have a place around legalizer where we could combine extending artifacts with some instructions, as combining instruction with G_AND (or some other bitwise instr) seem like much more work later that could be done earlier. Its better to not produce superfluous extend (bitwise instr) instruction at all, then deal with it later.<br />It would also be nice if it could be possible to choose if extend instructions are replaced with bitwise instructions or not. Not replacing them in early passes will give us fewer instructions to work with and carry on in later passes. It would let us select extend in instruction-select. This approach could result in using a little less memory. Also some mips processors have instructions that extract bits or do sign extend. These could be selected from G_ZEXT or G_SEXT generating single instruction instead of two equivalent bitwise instructions.<br /><br />Q: I see that there is a plan to add pre/post legalizer combining pass. Where should combining happen, in pre/post legalizer combining pass or in the instruction select pass?<br /><br />For example, G_SELECT could be selected into 'movn', the default option, i.e. move on true.<br />However, G_SELECT where test is defined with G_ICMP, could be selected into movz or movn based on compare opcode (opcode that requires negation (with xor) could be selected into movz and remove xor (or into movn with but we need to swap true and false register)). If we select icmp and select independently we could end up with an extra xor instruction.<br /><br />I ask this question since combination of G_LOAD and G_SEXT<br /><br /> %1:_(s8) = G_LOAD %0(p0)<br /> %2:_(s32) = G_SEXT %1(s8)<br /><br />will be replaced with G_SEXTLOAD in upcoming combiner. And if we let %1:_(s8) = G_LOAD %0(p0) to be legal, we could select G_SEXT into G_LOAD (going bottom up) into sign extending load of appropriate size in instruction-select.<br /><br />Best regards,<br />Petar<br /> </html>