Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion llvm/lib/Analysis/HashRecognize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,11 @@ std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const {

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

// Check that the SelectInst ConditionalRecurrence.Step is conditional on
Expand Down
81 changes: 81 additions & 0 deletions llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1448,4 +1448,85 @@ exit: ; preds = %loop
ret i16 %crc.next
}

define i16 @not.crc.data.next.outside.user(i16 %crc.init, i16 %data.init) {
; CHECK-LABEL: 'not.crc.data.next.outside.user'
; CHECK-NEXT: Did not find a hash algorithm
; CHECK-NEXT: Reason: Recurrences have stray uses
;
entry:
br label %loop

loop:
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %data, %crc
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 3
%check.sb = icmp slt i16 %xor.crc.data, 0
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
%data.next = shl i16 %data, 1
%iv.next = add nuw nsw i32 %iv, 1
%exit.cond = icmp samesign ult i32 %iv, 7
br i1 %exit.cond, label %loop, label %exit

exit:
%ret = xor i16 %data.next, %crc.next
ret i16 %ret
}

define i16 @not.crc.data.phi.outside.user(i16 %crc.init, i16 %data.init) {
; CHECK-LABEL: 'not.crc.data.phi.outside.user'
; CHECK-NEXT: Did not find a hash algorithm
; CHECK-NEXT: Reason: Recurrences have stray uses
;
entry:
br label %loop

loop:
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %data, %crc
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 3
%check.sb = icmp slt i16 %xor.crc.data, 0
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
%data.next = shl i16 %data, 1
%iv.next = add nuw nsw i32 %iv, 1
%exit.cond = icmp samesign ult i32 %iv, 7
br i1 %exit.cond, label %loop, label %exit

exit:
%ret = xor i16 %data, %crc.next
ret i16 %ret
}

define i16 @not.crc.crc.phi.outside.user(i16 %crc.init, i16 %data.init) {
; CHECK-LABEL: 'not.crc.crc.phi.outside.user'
; CHECK-NEXT: Did not find a hash algorithm
; CHECK-NEXT: Reason: Recurrences have stray uses
;
entry:
br label %loop

loop:
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %data, %crc
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 3
%check.sb = icmp slt i16 %xor.crc.data, 0
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
%data.next = shl i16 %data, 1
%iv.next = add nuw nsw i32 %iv, 1
%exit.cond = icmp samesign ult i32 %iv, 7
br i1 %exit.cond, label %loop, label %exit

exit:
%ret = xor i16 %crc, %crc.next
ret i16 %ret
}

declare i16 @side.effect()
46 changes: 46 additions & 0 deletions llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,52 @@ exit: ; preds = %loop
%ret = and i32 %unrelated.next, %crc.next
ret i32 %ret
}

define i16 @not.crc.data.next.outside.user(i16 %crc.init, i16 %data.init) {
; CHECK-LABEL: define i16 @not.crc.data.next.outside.user(
; CHECK-SAME: i16 [[CRC_INIT:%.*]], i16 [[DATA_INIT:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[TBL_LD:%.*]] = phi i16 [ [[CRC_INIT]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[CRC_BE_SHIFT:%.*]] = phi i16 [ [[DATA_INIT]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[CRC_NEXT3:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
; CHECK-NEXT: [[CRC_SHL:%.*]] = shl i16 [[TBL_LD]], 1
; CHECK-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 3
; CHECK-NEXT: [[CHECK_SB:%.*]] = icmp slt i16 [[CRC_NEXT3]], 0
; CHECK-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_XOR]], i16 [[CRC_SHL]]
; CHECK-NEXT: [[DATA_NEXT]] = shl i16 [[CRC_BE_SHIFT]], 1
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i32 [[IV]], 7
; CHECK-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; CHECK-NEXT: [[DATA_NEXT_LCSSA:%.*]] = phi i16 [ [[DATA_NEXT]], %[[LOOP]] ]
; CHECK-NEXT: [[RET:%.*]] = xor i16 [[DATA_NEXT_LCSSA]], [[CRC_NEXT_LCSSA]]
; CHECK-NEXT: ret i16 [[RET]]
;
entry:
br label %loop

loop:
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %data.init, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %data, %crc
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 3
%check.sb = icmp slt i16 %xor.crc.data, 0
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
%data.next = shl i16 %data, 1
%iv.next = add nuw nsw i32 %iv, 1
%exit.cond = icmp samesign ult i32 %iv, 7
br i1 %exit.cond, label %loop, label %exit

exit:
%ret = xor i16 %data.next, %crc.next
ret i16 %ret
}
;.
; CHECK: attributes #[[ATTR0]] = { optsize }
;.