Skip to content

Commit 91e8079

Browse files
committed
[X86] Teach PostprocessISelDAG to fold ANDrm+TESTrr when chain result is used.
The isOnlyUserOf prevented the fold if the chain result had any users. What we really care about is the the data result from the AND is only used by the TEST, and the flags results from the ANDs aren't used at all. It's ok if the chain has users, we just need to replace those users with the chain from the TESTrm. Reviewed By: LuoYuanke Differential Revision: https://reviews.llvm.org/D131117
1 parent c988c26 commit 91e8079

File tree

2 files changed

+13
-11
lines changed

2 files changed

+13
-11
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,12 +1487,13 @@ void X86DAGToDAGISel::PostprocessISelDAG() {
14871487
if ((Opc == X86::TEST8rr || Opc == X86::TEST16rr ||
14881488
Opc == X86::TEST32rr || Opc == X86::TEST64rr) &&
14891489
N->getOperand(0) == N->getOperand(1) &&
1490-
N->isOnlyUserOf(N->getOperand(0).getNode()) &&
1490+
N->getOperand(0)->hasNUsesOfValue(2, N->getOperand(0).getResNo()) &&
14911491
N->getOperand(0).isMachineOpcode()) {
14921492
SDValue And = N->getOperand(0);
14931493
unsigned N0Opc = And.getMachineOpcode();
1494-
if (N0Opc == X86::AND8rr || N0Opc == X86::AND16rr ||
1495-
N0Opc == X86::AND32rr || N0Opc == X86::AND64rr) {
1494+
if ((N0Opc == X86::AND8rr || N0Opc == X86::AND16rr ||
1495+
N0Opc == X86::AND32rr || N0Opc == X86::AND64rr) &&
1496+
!And->hasAnyUseOfValue(1)) {
14961497
MachineSDNode *Test = CurDAG->getMachineNode(Opc, SDLoc(N),
14971498
MVT::i32,
14981499
And.getOperand(0),
@@ -1501,8 +1502,9 @@ void X86DAGToDAGISel::PostprocessISelDAG() {
15011502
MadeChange = true;
15021503
continue;
15031504
}
1504-
if (N0Opc == X86::AND8rm || N0Opc == X86::AND16rm ||
1505-
N0Opc == X86::AND32rm || N0Opc == X86::AND64rm) {
1505+
if ((N0Opc == X86::AND8rm || N0Opc == X86::AND16rm ||
1506+
N0Opc == X86::AND32rm || N0Opc == X86::AND64rm) &&
1507+
!And->hasAnyUseOfValue(1)) {
15061508
unsigned NewOpc;
15071509
switch (N0Opc) {
15081510
case X86::AND8rm: NewOpc = X86::TEST8mr; break;
@@ -1523,7 +1525,8 @@ void X86DAGToDAGISel::PostprocessISelDAG() {
15231525
MVT::i32, MVT::Other, Ops);
15241526
CurDAG->setNodeMemRefs(
15251527
Test, cast<MachineSDNode>(And.getNode())->memoperands());
1526-
ReplaceUses(N, Test);
1528+
ReplaceUses(And.getValue(2), SDValue(Test, 1));
1529+
ReplaceUses(SDValue(N, 0), SDValue(Test, 0));
15271530
MadeChange = true;
15281531
continue;
15291532
}

llvm/test/CodeGen/X86/cmp.ll

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -759,14 +759,13 @@ return: ; preds = %if.end, %if.then
759759
declare i32 @g()
760760
declare i32 @f()
761761

762-
; FIXME: We should use a test from memory here instead of a load+and.i
763-
; The store makes sure the chain result of the load is used which prevents the
764-
; post isel peephole from catching this.
762+
; Make sure we fold the load+and into a test from memory.
763+
; The store makes sure the chain result of the load is used which used to
764+
; prevent the post isel peephole from catching this.
765765
define i1 @fold_test_and_with_chain(i32* %x, i32* %y, i32 %z) {
766766
; CHECK-LABEL: fold_test_and_with_chain:
767767
; CHECK: # %bb.0:
768-
; CHECK-NEXT: movl (%rdi), %eax # encoding: [0x8b,0x07]
769-
; CHECK-NEXT: andl %edx, %eax # encoding: [0x21,0xd0]
768+
; CHECK-NEXT: testl %edx, (%rdi) # encoding: [0x85,0x17]
770769
; CHECK-NEXT: sete %al # encoding: [0x0f,0x94,0xc0]
771770
; CHECK-NEXT: movl %edx, (%rsi) # encoding: [0x89,0x16]
772771
; CHECK-NEXT: retq # encoding: [0xc3]

0 commit comments

Comments
 (0)