Skip to content

Commit 72eaa0e

Browse files
[AArch64][SelectionDAG] Mask for SUBS with multiple users cannot be elided (#90911)
In DAGCombiner, the `performCONDCombine` function attempts to remove AND instructions in front of SUBS (cmp) instructions for which the AND is transparent. The rules for that are correct, but it fails to take into account the case where the SUBS instruction has multiple users with different condition codes for comparison and simply removes the AND for all of them. This causes a miscompilation in the attached test case.
1 parent 7963d9a commit 72eaa0e

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22833,7 +22833,8 @@ SDValue performCONDCombine(SDNode *N,
2283322833
SDNode *SubsNode = N->getOperand(CmpIndex).getNode();
2283422834
unsigned CondOpcode = SubsNode->getOpcode();
2283522835

22836-
if (CondOpcode != AArch64ISD::SUBS || SubsNode->hasAnyUseOfValue(0))
22836+
if (CondOpcode != AArch64ISD::SUBS || SubsNode->hasAnyUseOfValue(0) ||
22837+
!SubsNode->hasOneUse())
2283722838
return SDValue();
2283822839

2283922840
// There is a SUBS feeding this condition. Is it fed by a mask we can

llvm/test/CodeGen/AArch64/and-mask-removal.ll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,4 +526,26 @@ define i64 @pr58109b(i8 signext %0, i64 %a, i64 %b) {
526526
ret i64 %4
527527
}
528528

529+
define i64 @test_2_selects(i8 zeroext %a) {
530+
; CHECK-LABEL: test_2_selects:
531+
; CHECK: ; %bb.0:
532+
; CHECK-NEXT: add w9, w0, #24
533+
; CHECK-NEXT: mov w8, #131
534+
; CHECK-NEXT: and w9, w9, #0xff
535+
; CHECK-NEXT: cmp w9, #81
536+
; CHECK-NEXT: mov w9, #57
537+
; CHECK-NEXT: csel x8, x8, xzr, lo
538+
; CHECK-NEXT: csel x9, xzr, x9, eq
539+
; CHECK-NEXT: add x0, x8, x9
540+
; CHECK-NEXT: ret
541+
%1 = add i8 %a, 24
542+
%2 = zext i8 %1 to i64
543+
%3 = icmp ult i8 %1, 81
544+
%4 = select i1 %3, i64 131, i64 0
545+
%5 = icmp eq i8 %1, 81
546+
%6 = select i1 %5, i64 0, i64 57
547+
%7 = add i64 %4, %6
548+
ret i64 %7
549+
}
550+
529551
declare i8 @llvm.usub.sat.i8(i8, i8) #0

0 commit comments

Comments
 (0)