Skip to content

Commit 3bc9b28

Browse files
authored
[HashRecognize] Forbid optz when data.next has exit-block user (llvm#165574)
The CRC optimization relies on stripping the auxiliary data completely, and should hence be forbidden when it has a user in the exit-block. Forbid this case, fixing a miscompile. Fixes llvm#165382.
1 parent 242ebcf commit 3bc9b28

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

llvm/lib/Analysis/HashRecognize.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,11 @@ std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const {
468468

469469
// Ensure that the PHIs have exactly two uses:
470470
// the bit-shift, and the XOR (or a cast feeding into the XOR).
471+
// Also ensure that the SimpleRecurrence's evolution doesn't have stray
472+
// users.
471473
if (!ConditionalRecurrence.Phi->hasNUses(2) ||
472-
!SimpleRecurrence.Phi->hasNUses(2))
474+
!SimpleRecurrence.Phi->hasNUses(2) ||
475+
SimpleRecurrence.BO->getUniqueUndroppableUser() != SimpleRecurrence.Phi)
473476
return "Recurrences have stray uses";
474477

475478
// Check that the SelectInst ConditionalRecurrence.Step is conditional on

llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,4 +1448,85 @@ exit: ; preds = %loop
14481448
ret i16 %crc.next
14491449
}
14501450

1451+
define i16 @not.crc.data.next.outside.user(i16 %crc.init, i16 %data.init) {
1452+
; CHECK-LABEL: 'not.crc.data.next.outside.user'
1453+
; CHECK-NEXT: Did not find a hash algorithm
1454+
; CHECK-NEXT: Reason: Recurrences have stray uses
1455+
;
1456+
entry:
1457+
br label %loop
1458+
1459+
loop:
1460+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
1461+
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
1462+
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
1463+
%xor.crc.data = xor i16 %data, %crc
1464+
%crc.shl = shl i16 %crc, 1
1465+
%crc.xor = xor i16 %crc.shl, 3
1466+
%check.sb = icmp slt i16 %xor.crc.data, 0
1467+
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
1468+
%data.next = shl i16 %data, 1
1469+
%iv.next = add nuw nsw i32 %iv, 1
1470+
%exit.cond = icmp samesign ult i32 %iv, 7
1471+
br i1 %exit.cond, label %loop, label %exit
1472+
1473+
exit:
1474+
%ret = xor i16 %data.next, %crc.next
1475+
ret i16 %ret
1476+
}
1477+
1478+
define i16 @not.crc.data.phi.outside.user(i16 %crc.init, i16 %data.init) {
1479+
; CHECK-LABEL: 'not.crc.data.phi.outside.user'
1480+
; CHECK-NEXT: Did not find a hash algorithm
1481+
; CHECK-NEXT: Reason: Recurrences have stray uses
1482+
;
1483+
entry:
1484+
br label %loop
1485+
1486+
loop:
1487+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
1488+
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
1489+
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
1490+
%xor.crc.data = xor i16 %data, %crc
1491+
%crc.shl = shl i16 %crc, 1
1492+
%crc.xor = xor i16 %crc.shl, 3
1493+
%check.sb = icmp slt i16 %xor.crc.data, 0
1494+
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
1495+
%data.next = shl i16 %data, 1
1496+
%iv.next = add nuw nsw i32 %iv, 1
1497+
%exit.cond = icmp samesign ult i32 %iv, 7
1498+
br i1 %exit.cond, label %loop, label %exit
1499+
1500+
exit:
1501+
%ret = xor i16 %data, %crc.next
1502+
ret i16 %ret
1503+
}
1504+
1505+
define i16 @not.crc.crc.phi.outside.user(i16 %crc.init, i16 %data.init) {
1506+
; CHECK-LABEL: 'not.crc.crc.phi.outside.user'
1507+
; CHECK-NEXT: Did not find a hash algorithm
1508+
; CHECK-NEXT: Reason: Recurrences have stray uses
1509+
;
1510+
entry:
1511+
br label %loop
1512+
1513+
loop:
1514+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
1515+
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
1516+
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
1517+
%xor.crc.data = xor i16 %data, %crc
1518+
%crc.shl = shl i16 %crc, 1
1519+
%crc.xor = xor i16 %crc.shl, 3
1520+
%check.sb = icmp slt i16 %xor.crc.data, 0
1521+
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
1522+
%data.next = shl i16 %data, 1
1523+
%iv.next = add nuw nsw i32 %iv, 1
1524+
%exit.cond = icmp samesign ult i32 %iv, 7
1525+
br i1 %exit.cond, label %loop, label %exit
1526+
1527+
exit:
1528+
%ret = xor i16 %crc, %crc.next
1529+
ret i16 %ret
1530+
}
1531+
14511532
declare i16 @side.effect()

llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,52 @@ exit: ; preds = %loop
537537
%ret = and i32 %unrelated.next, %crc.next
538538
ret i32 %ret
539539
}
540+
541+
define i16 @not.crc.data.next.outside.user(i16 %crc.init, i16 %data.init) {
542+
; CHECK-LABEL: define i16 @not.crc.data.next.outside.user(
543+
; CHECK-SAME: i16 [[CRC_INIT:%.*]], i16 [[DATA_INIT:%.*]]) {
544+
; CHECK-NEXT: [[ENTRY:.*]]:
545+
; CHECK-NEXT: br label %[[LOOP:.*]]
546+
; CHECK: [[LOOP]]:
547+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
548+
; CHECK-NEXT: [[TBL_LD:%.*]] = phi i16 [ [[CRC_INIT]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
549+
; CHECK-NEXT: [[CRC_BE_SHIFT:%.*]] = phi i16 [ [[DATA_INIT]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
550+
; CHECK-NEXT: [[CRC_NEXT3:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
551+
; CHECK-NEXT: [[CRC_SHL:%.*]] = shl i16 [[TBL_LD]], 1
552+
; CHECK-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 3
553+
; CHECK-NEXT: [[CHECK_SB:%.*]] = icmp slt i16 [[CRC_NEXT3]], 0
554+
; CHECK-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_XOR]], i16 [[CRC_SHL]]
555+
; CHECK-NEXT: [[DATA_NEXT]] = shl i16 [[CRC_BE_SHIFT]], 1
556+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
557+
; CHECK-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i32 [[IV]], 7
558+
; CHECK-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
559+
; CHECK: [[EXIT]]:
560+
; CHECK-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
561+
; CHECK-NEXT: [[DATA_NEXT_LCSSA:%.*]] = phi i16 [ [[DATA_NEXT]], %[[LOOP]] ]
562+
; CHECK-NEXT: [[RET:%.*]] = xor i16 [[DATA_NEXT_LCSSA]], [[CRC_NEXT_LCSSA]]
563+
; CHECK-NEXT: ret i16 [[RET]]
564+
;
565+
entry:
566+
br label %loop
567+
568+
loop:
569+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
570+
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
571+
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
572+
%xor.crc.data = xor i16 %data, %crc
573+
%crc.shl = shl i16 %crc, 1
574+
%crc.xor = xor i16 %crc.shl, 3
575+
%check.sb = icmp slt i16 %xor.crc.data, 0
576+
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
577+
%data.next = shl i16 %data, 1
578+
%iv.next = add nuw nsw i32 %iv, 1
579+
%exit.cond = icmp samesign ult i32 %iv, 7
580+
br i1 %exit.cond, label %loop, label %exit
581+
582+
exit:
583+
%ret = xor i16 %data.next, %crc.next
584+
ret i16 %ret
585+
}
540586
;.
541587
; CHECK: attributes #[[ATTR0]] = { optsize }
542588
;.

0 commit comments

Comments
 (0)