<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi Eli,<div class=""><br class=""></div><div class="">Thank  you very much for your response. </div><div class=""><br class=""></div><div class="">In fact, I had already tried the X86 approach before, i.e explicitly using the status register. This is the approach that appeals more to me. I left it parked because it also produced some problems (but I left it commented out). So I have now re-lived the code, and it works fine in most cases, but there’s a particular case that causes LLVM to stop with an assertion. Apparently LLVM tries to use the SR (Status Register) register as a general purpose one, which is not allowed in my architecture. The problem exists even before I added the referred optimisations. The code that causes the problem is this:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">int</span> doSmth( <span style="color: #ba2da2" class="">int</span> y );</div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class=""><span style="color: #ba2da2" class="">int</span> test( <span style="color: #ba2da2" class="">int</span> y )</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class="">{</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class="">  <span style="color: #ba2da2" class="">int</span> neg = y < <span style="color: #272ad8" class="">0</span>;</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class="">  <span style="color: #ba2da2" class="">if</span> ( neg )</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class="">    y = - y;</div><p style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255); min-height: 15px;" class="">  <br class="webkit-block-placeholder"></p><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class="">  <span style="color: #ba2da2" class="">int</span> rv = doSmth( y );</div><p style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255); min-height: 15px;" class="">  <br class="webkit-block-placeholder"></p><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class="">  <span style="color: #ba2da2" class="">return</span> neg ? - rv : rv;</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Monaco; background-color: rgb(255, 255, 255);" class="">}</div></div><div class=""><br class=""></div><div class="">Apparently, LLVM attempts to physically use the result of a CMP instruction through a function call by storing it on a temporary register. This is found before the doSmth function call, </div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class="">  t30: i16 = CMPkr16 t4, TargetConstant:i16<0></b></span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class="">    t36: ch,glue = CopyToReg t0, Register:i16 $sr, t30</b></span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class="">  t32: i16 = NEGSETCC TargetConstant:i16<4>, t36:1</b></span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class=""><br class=""></b></span></div></div></div></div><div class="">And this is generated after the call</div><div class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class="">      t35: ch,glue = CopyToReg t0, Register:i16 $sr, t30</b></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class="">    t31: i16 = SELCC t19, t18, TargetConstant:i16<4>, t35:1</b></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class="">  t21: ch,glue = CopyToReg t18:1, Register:i16 $r0, t31</b></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><b class=""> </b></div><div class="">NEGSETCC and SELCC are genuine instructions of my target architecture, they use the SR along with operands to produce a result.</div><div class=""><br class=""></div><div class="">As you can see ‘t30’ is used both before and after the function call, which is what I think that causes trouble. In particular, the assertion that I get is this:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><b class="">Assertion failed: (RegClass->isAllocatable() && "Virtual register RegClass must be allocatable."), function createVirtualRegister, file /Users/joan/LLVM+CLANG/llvm-7.0.1.src/lib/CodeGen/MachineRegisterInfo.cpp, line 170.</b></span></div></div><div class=""><br class=""></div><div class="">If I remove the ‘isAllocatable=0’ setting on the SR register, then LLVM will try to spill the SR by calling ‘storeRegToStackSlot’, which then I stop with my own assertion because the SR can’t be spilled.</div><div class=""><br class=""></div><div class="">If I then remove also the ‘let CopCost = -1’ for the SR register, then LLVM attempts to move it to a general purpose register by calling ‘copyPhysRegs’, which again I stop with an assertion because it’s not legal in my architecture.</div><div class=""><br class=""></div><div class="">So, I’m stuck as well with this approach.</div><div class=""><br class=""></div><div class="">Any ideas, on what I can try?</div><div class=""><br class=""></div><div class="">I think, that at this point I need to stop LLVM from attempting to reuse the result of the CMP instruction before and after the function call, and instead make it generate a new cmp instruction after the call. But how do I achieve that?</div><div class=""><br class=""></div><div class="">(maybe a difficulty is that I am Custom lowering ’’SELECT_CC’ and ‘BR_CC’, and Expanding ’SELECT’ and ‘BRCOND’, instead of the opposite? Does this make a difference?)</div><div class=""><br class=""></div><div class="">Thanks</div><div class=""><br class=""><div class="">
<div style="color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Joan Lluch<br class=""><br class="">Tel: 620 28 45 13</div></div></div>
</div>
<br class=""><div><blockquote type="cite" class=""><div class="">On 2 Jun 2019, at 03:23, Eli Friedman <<a href="mailto:efriedma@quicinc.com" class="">efriedma@quicinc.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class="">There are basically two possible approaches here.</div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class="">One approach is to just wait until after isel to handle this: check for an addition instruction immediately followed by an cmp; then erase the cmp. See, for example,<span class="pl-en"> ARMBaseInstrInfo::optimizeCompareInstr</span>.<br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class="">Another, you make a dedicated target-specific ISel node that produces two results: essentially, one is the result of the arithmetic, and the other is the status register.  See, for example, X86TargetLowering::LowerBRCOND.</div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class="">I don't think you'd want to try to do anything in Select(); I mean, you could try to pattern-match (cmp x, (add x, y)) or whatever, but you'd probably run into trouble if the add has multiple uses.<br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=""><br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class="">-Eli<br class=""></div><div style="margin-top: 0px; margin-bottom: 0px; font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=""><br class=""></div><div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); word-wrap: break-word;" class=""><hr tabindex="-1" style="display: inline-block; width: 1072.109375px;" class=""><div id="divRplyFwdMsg" dir="ltr" class=""><font face="Calibri, sans-serif" style="font-size: 11pt;" class=""><b class="">From:</b><span class="Apple-converted-space"> </span>llvm-dev <<a href="mailto:llvm-dev-bounces@lists.llvm.org" class="">llvm-dev-bounces@lists.llvm.org</a>> on behalf of Joan Lluch via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" class="">llvm-dev@lists.llvm.org</a>><br class=""><b class="">Sent:</b><span class="Apple-converted-space"> </span>Saturday, June 1, 2019 10:09 AM<br class=""><b class="">To:</b><span class="Apple-converted-space"> </span>llvm-dev<br class=""><b class="">Subject:</b><span class="Apple-converted-space"> </span>[EXT] [llvm-dev] Optimizing Compare instruction selection</font><div class=""> </div></div><div class="">I attempt to optimize the use of the ‘CMP’ instruction on my architecture by removing the instruction instances where the Status Register already had the correct status flags.<div class=""><br class=""></div><div class="">The cmp instruction in my architecture is the typical one that compares two registers, or a register with an immediate, and sets the Status Flags accordingly. I implemented my ‘cmp’  instruction in LLVM by custom lowering the SETCC, SELECT_CC and BR_CC in the usual way, mostly following the ARM implementation. In particular the target cmp instruction is created and glued to a target conditional instruction, such as a conditional branch, or a conditional select. </div><div class=""><br class=""></div><div class="">The generated code may look like this:</div><div class=""><br class=""></div><div class="">add R0, R1, R2</div><div class="">cmp R0, #0</div><div class="">breq Label</div><div class=""><br class=""></div><div class="">This works fine, but now I would want to go one step further:</div><div class=""><br class=""></div><div class="">As part of the SETCC and SELECT_CC lowering, I can determine if the conditions are met in my architecture to avoid generating a ‘cmp’ instruction at all. For example, if the left operand of the SETCC is an ‘addition', the right operand is constant zero, and the condition is 'ISD::CondCode::SETEQ, I can safely assume that the Status Register in my architecture already has the right condition just before the ‘cmp’, which has been set by the target ‘add’ instruction. So at this point I want to avoid generating the ‘cmp’ because it is redundant. </div><div class=""><br class=""></div><div class="">My goal is to replace the assembly code shown above, by just this:</div><div class=""><div class=""><br class=""></div><div class=""><div class="">add R0, R1, R2</div><div class="">breq Label</div></div><div class=""><br class=""></div><div class="">The ‘cmp’ was redundant in this case because the add instruction already set the Z (zero) flag</div></div><div class=""><br class=""></div><div class="">I tried several things, but I got stuck in some way in all of them. For example, an approach that I tried is to have a ‘dummy_cmp’ instruction, that I generate instead of the regular ‘cmp’ when the comparison is redundant. The ‘dummy_cmp’ must be removed at a latter stage, ideally during the selDAGToDAG phase, but I failed to do so. </div><div class=""><br class=""></div><div class="">- So my first question is. How do I remove the ‘dummy_cmp’ node in the MyTargetISelDAGtoDAG::Select() function?</div><div class=""><br class=""></div><div class="">Another approach that I tried, which I regard as preferable, is to directly avoid the creation of a ‘cmp’ instruction during ISelLowering. Instead of ‘cmp’, use the LHS operand of the SETCC operand if it mets the conditions described above. The problem that I found with this approach is that the ‘cmp’ is just a ‘glue’ to the target branch or select instruction, however, the LHS is an actual operand (for example an ‘add’ node), so I need to create a ‘glue’ for it, in order to be attached to the target branch instruction.</div><div class=""><br class=""></div><div class="">- My second question is therefore, how do I create a ‘glue’ for an existing ‘add’ node that I can attach to the target conditional instruction as a replacement of the ‘cmp’ instruction?   </div><div class=""><div class=""><br class=""></div><div class=""> <br class=""><div class=""><div class="" style="letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;"><div class="" style="word-wrap: break-word;"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" class="">Joan Lluch</div></div></div></div></div></div></div></div></div></blockquote></div><br class=""></div></body></html>