Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
8 changes: 8 additions & 0 deletions llvm/lib/Analysis/HashRecognize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,14 @@ std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const {
: LHS->getType()->getIntegerBitWidth()))
return "Loop iterations exceed bitwidth of data";

// Make sure that the simple recurrence evolution isn't used in the exit
// block.
if (SimpleRecurrence && any_of(SimpleRecurrence.BO->users(), [Exit](User *U) {
auto *UI = dyn_cast<Instruction>(U);
return UI && UI->getParent() == Exit;
}))
return "Recurrences have stray uses";

// Make sure that the computed value is used in the exit block: this should be
// true even if it is only really used in an outer loop's exit block, since
// the loop is in LCSSA form.
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 }
;.