<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 14 Sep 2018, at 06:50, pavram <<a href="mailto:Petar.Avramovic@rt-rk.com" class="">Petar.Avramovic@rt-rk.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" class="">
  
  <div text="#000000" bgcolor="#FFFFFF" class=""><p class=""><br class="">
    </p>
    <br class="">
    Hi Daniel,
    <br class="">
    <br class="">
    On 13.09.2018. 19:32, Daniel Sanders wrote:
    <br class="">
    <blockquote type="cite" style="" class="">Could you clarify
      what you mean here? The new legalizer info can define this with:
      <br class="">
          getActionDefinitionsBuilder(G_SELECT).clampScalar(1, s32, s32)
      <br class="">
      so I'm guessing you mean that code to mutate the G_SELECT is
      currently missing
      <br class="">
    </blockquote>
    Yes, LegalizerHelper::widenScalar widens only TypeIdx==0, it doesn't
    do that for TypeIdx==1. Is it intentionally implemented this way?
    <br class=""></div></div></blockquote><div><br class=""></div><div>No, we just haven't needed to implement the TypeIdx==1 case so far. Up until recently we didn't have a means to test things that weren't in use by a target. We decided it was better for the compiler to fail than to submit untested/untestable code so there's quite a few gaps like this.</div><br class=""><blockquote type="cite" class=""><div class=""><div text="#000000" bgcolor="#FFFFFF" class="">
    <blockquote type="cite" style="" class="">
      <blockquote type="cite" style="" class="">b) Is the plan to
        sometimes let s1 as legal type and ignore it later?
        <br class="">
      </blockquote>
      I'm not sure what you mean here
      <br class="">
      <br class="">
    </blockquote>
    For example lets look at AArch64 G_SELECT:
    <br class="">
      getActionDefinitionsBuilder(G_SELECT)
    <br class="">
          .legalFor({{s32, s1}, {s64, s1}, {p0, s1}})
    <br class="">
          .clampScalar(0, s32, s64)
    <br class="">
          .widenScalarToNextPow2(0);
    <br class="">
    <br class="">
    In this case LLT of operand 1 (s1) in G_SELECT has size 1, and
    corresponding register class in selected instruction has size 32
    (that is $src1 in AArch64::ANDSWri, it has GPR32 regsiter class).
    <br class="">
    For that reason s1 is practically ignored and silently converted to
    s32.<br class=""></div></div></blockquote><div><br class=""></div><div>Oh, I see what you mean. This is also a viable option but it requires that bits 1-31 don't affect the results of legal operations no matter what value they are. This makes little difference to something like G_ADD, but things like G_LSHR (that one isn't really an issue for s1, but applies for s2-s30) have to ensure they insert leading zeros even if the bits in the container are 1's. Of course, you don't have to declare the difficult operations to be legal and can let them widenScalar up to a type that's easy to deal with.</div><div><br class=""></div><div>For Mips, this approach is probably ok so long as G_TRUNC defines bits 1-31 and any other s1-producing operations that are legal maintain those bits to keep them at the value they would be if you had only just done the G_TRUNC. I expect you only want G_TRUNC/G_ANYEXT/G_SEXT/G_ZEXT, G_ICMP/G_FCMP, and G_OR/G_XOR/G_AND in which case it's easy to achieve this.</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div text="#000000" bgcolor="#FFFFFF" class="">We could get similar result if we have:
    <br class="">
    <br class="">
      getActionDefinitionsBuilder(G_SELECT)
    <br class="">
          .legalFor({{s32, s32}, {s64, s32}, {p0, s32}})
    <br class="">
          .clampScalar(0, s32, s64)
    <br class="">
          .clampScalar(1, s32, s32)
    <br class="">
          .widenScalarToNextPow2(0);
    <br class="">
    <br class="">
    And in this case sizes of LLTs and register classes would be the
    same.
    <br class="">
    Implementation for G_ICMP on AArch64 is very similar to second
    described option for G_SELECT.
    <br class="">
    Is there a reason for different implementation of G_SELECT and
    G_ICMP on AArch64? Are there some general ruses to determine which
    of the two given options is better in which case?</div></div></blockquote><br class=""></div><div>At the moment, it largely comes down to preference. I don't have any real evidence to back this up but I expect the latter will be the better optimized in the long run since maintaining the excess bits requires instructions and these are explicit in the GMIR. This means we can optimize it and decline to do it whenever it doesn't matter. For example:</div><div><span class="Apple-tab-span" style="white-space:pre">       </span>%2(s2) = G_ADD %0(s2), %1(s2)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>%4(s2) = G_ADD %2(s2), %3(s2)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>%5(s2) = G_LSHR %4(s2), i2 1</div><div>has to either preserve bits 2-31 between each operation just in case one that cares about it comes along, or define bits 2-31 just before an operation that cares about it even if they're already correct. This costs six and instructions. Whereas:</div><div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>%3(s32) = G_AND %0(s2), i32 3</div><div><span class="Apple-tab-span" style="white-space: pre;">      </span>%4(s32) = G_AND %1(s2), i32 3</div><div><span class="Apple-tab-span" style="white-space: pre;">      </span>%5(s32) = G_AND %2(s2), i32 3</div></div><div><span class="Apple-tab-span" style="white-space: pre;">  </span>%6(s32) = G_ADD %3(s32), %4(s32)</div><div><span class="Apple-tab-span" style="white-space:pre">     </span>%7(s32) = G_AND %6(s32), i32 3</div><div><div><div></div></div><div><span class="Apple-tab-span" style="white-space: pre;">    </span>%8(s32) = G_ADD %5(s32), %7(s32)</div><div><span class="Apple-tab-span" style="white-space: pre;">   </span>%9(s32) = G_AND %8(s32), i32 3</div><div><span class="Apple-tab-span" style="white-space: pre;">     </span>%10(s32) = G_LSHR %9(s32), i2 1</div><div><span class="Apple-tab-span" style="white-space: pre;">    </span>%11(s32) = G_AND %9(s32), i32 3</div><div>can optimize to:</div><div><div><span class="Apple-tab-span" style="white-space: pre;">  </span>%6(s32) = G_ADD %0(s32), %1(s32)</div><div><span class="Apple-tab-span" style="white-space: pre;">   </span>%8(s32) = G_ADD %2(s32), %6(s32)</div><div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>%10(s32) = G_LSHR %8(s32), i2 1</div><div><span class="Apple-tab-span" style="white-space: pre;">    </span>%11(s32) = G_AND %9(s32), i32 1</div><div>which costs only one and instruction.</div></div></div></div></body></html>