This is an archive of the discontinued LLVM Phabricator instance.

[SplitKit] Handle early clobber + tied to def correctly
ClosedPublic

Authored by kito-cheng on May 20 2022, 1:15 AM.

Details

Summary

Spliter will try to extend a live range into r slot for a use operand,
that's works on most situaion, however that not work correctly when the operand
has tied to def, and the def operand is early clobber.

Give an example to demo what's wrong:

0  %0 = ...

16 early-clobber %0 = Op %0 (tied-def 0), ...
32 ... = Op %0

Before extend:
%0 = [0r, 0d) [16e, 32d)

The point we want to extend is 0d to 16e not 16r in this case, but if
we use 16r here we will extend nothing because that already contained
in [16e, 32d).

This patch add check for detect such case and adjust the extend point.

Detailed explanation for testcase: https://reviews.llvm.org/D126047

Diff Detail

Event Timeline

kito-cheng created this revision.May 20 2022, 1:15 AM
kito-cheng requested review of this revision.May 20 2022, 1:15 AM
kito-cheng edited the summary of this revision. (Show Details)May 20 2022, 1:19 AM
kito-cheng added reviewers: craig.topper, reames, MatzeB.

This seems to make sense to me (though I am not super familiar with the code here). Some ideas for clearer code below:

llvm/lib/CodeGen/SplitKit.cpp
1354–1391

Hmm I found the (existing) logic here somewhat confusing... line 1361 doing getNextSlot() just seems to counteract line 1355 moving to the previous slot, but forces line 1359 to unnaturally chose the early clobber slot.

Anyway can we streamline the code somewhat like this:

1405

Use getOperandNo that's faster and avoids trouble if multiple operands use the same register.

Changes:

  • Address @MatzeB's commnet
  • Rebase and fix a regression.
kito-cheng marked an inline comment as done.May 27 2022, 2:18 AM
kito-cheng added inline comments.
llvm/lib/CodeGen/SplitKit.cpp
1354–1391

Thanks!

1405

Seems like getOperandNo only work with iterator? and that is what we don't have here :(

Anyway I change to that, but it is because I hit a regression for a testcase from X86...so I just try to traverse all input operand see which operand is tied-def and using same register as MO here...

See CodeGen/X86/statepoint-invoke-ra.mir:

dead %40:gr64 = STATEPOINT 2882400000, 0, 1, target-flags(x86-plt) @quux, $edi, 2, 0, 2, 0, 2, 6, 1, 4, %stack.0, 0, 1, 4, %stack.1, 0, 1, 4, %stack.2, 0, 1, 4, %stack.3, 0, %40:gr64, 1, 4, %stack.4, 0, 2, 1, %40:gr64(tied-def 0), 2, 0, 2, 1, 0, 0, <regmask $bh $bl $bp $bph $bpl $bx $ebp $ebx $hbp $hbx $rbp $rbx $r12 $r13 $r14 $r15 $r12b $r13b $r14b $r15b $r12bh $r13bh $r14bh $r15bh $r12d $r13d $r14d $r15d $r12w $r13w $r14w $r15w $r12wh and 3 more...>, implicit-def $rsp, implicit-def $ssp :: (volatile load store (s32) on %stack.0), (volatile load store (s32) on %stack.1), (volatile load store (s32) on %stack.2), (volatile load store (s32) on %stack.3), (volatile load store (s32) on %stack.4)

%40 appeared 3 times in this instruction, one for def, and two for use, and only one def has tied-def 0.

arcbbb added a subscriber: arcbbb.May 31 2022, 1:04 AM
arcbbb added inline comments.
llvm/lib/CodeGen/SplitKit.cpp
1381

The logic here looks similar to LiveIntervalCalc::extendToUses that checks for early-clobber redefs.
Can it be simplified with OpIdx = (&MO - &MI->getOperand(0)) and MI->isRegTiedToDefOperand(OpIdx, &DefOpIdx)?

kito-cheng marked an inline comment as done.May 31 2022, 5:47 AM
kito-cheng added inline comments.
llvm/lib/CodeGen/SplitKit.cpp
1381

MI->getOperandNo(MOItr) did almost similar thing[1] as (&MO - &MI->getOperand(0)), but having better readability.

And isRegTiedToDefOperand called findTiedOperandIdx in the function implementation[2], so I am not sure it's a simplification?

[1] https://llvm.org/doxygen/MachineInstr_8h_source.html#l00685
[2] https://llvm.org/doxygen/MachineInstr_8h_source.html#l00685

arcbbb added inline comments.May 31 2022, 6:49 AM
llvm/lib/CodeGen/SplitKit.cpp
1381

I think it can save the for loop and do checks for you
so the code would look like

-    } else
-      Idx = Idx.getRegSlot(true);
+    } else {
+      unsigned OpNo = MI->getOperandNo(&MO);
+      unsigned DefIdx;
+      bool isEarlyClobber = false;
+      if (MI->isRegTiedToDefOperand(OpNo, &DefIdx))
+        isEarlyClobber = MI->getOperand(DefIdx).isEarlyClobber();
+      Idx = Idx.getRegSlot(isEarlyClobber);
+    }
MatzeB added inline comments.May 31 2022, 8:44 AM
llvm/lib/CodeGen/SplitKit.cpp
1405

Well it's defined as using const_mop_iterator = const MachineOperand *;, so you should be good passing in the pointer, there's a some other places in the code that do the same.

MatzeB added inline comments.May 31 2022, 8:46 AM
llvm/lib/CodeGen/SplitKit.cpp
1373–1380
kito-cheng updated this revision to Diff 433339.Jun 1 2022, 3:04 AM
kito-cheng marked 5 inline comments as done.

Changes:

llvm/lib/CodeGen/SplitKit.cpp
1381

Thanks, save the loop seems great!

1405

Thanks, I didn't notice it's just an alias name of MachineOperand pointer :P

MatzeB accepted this revision.Jun 6 2022, 6:21 PM

LGTM, thanks

This revision is now accepted and ready to land.Jun 6 2022, 6:21 PM
This revision was landed with ongoing or failed builds.Jun 7 2022, 8:33 PM
This revision was automatically updated to reflect the committed changes.

Revert due to failed on LLVM_ENABLE_EXPENSIVE_CHECKS=On.

D127642 will resolved the LLVM_ENABLE_EXPENSIVE_CHECKS=On issue, will reland this patch after that land.

Allen added a subscriber: Allen.Aug 29 2022, 4:13 AM
Allen added inline comments.
llvm/lib/CodeGen/SplitKit.cpp
1369

sorry for the naive question, what's the mean of (tied-def 0)?

Does it only mean that the operand is early-clobber? or tied-def 0 implicit defined the higher bits are zero ?
I also don't known what is the mean of "0r, 0d, 16e and 32d".

MatzeB added inline comments.Aug 29 2022, 7:22 AM
llvm/lib/CodeGen/SplitKit.cpp
1369

when an operand is marked with tied-def 0 then it must get the same register assigned as operand 0 (after two-address instruction pass anyway).

16e etc. is the way slot indexes are printed (slot index 16, early clobber instruction slot). You could look in SlotIndexes.h or watch my regalloc tutorial from the developers meeting.