[llvm] r374811 - [LoopIdiom] BCmp: loop exit count must not be wider than size_t that `bcmp` takes
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 14 12:46:34 PDT 2019
Author: lebedevri
Date: Mon Oct 14 12:46:34 2019
New Revision: 374811
URL: http://llvm.org/viewvc/llvm-project?rev=374811&view=rev
Log:
[LoopIdiom] BCmp: loop exit count must not be wider than size_t that `bcmp` takes
As reported by Joerg Sonnenberger in IRC, for 32-bit systems,
where pointer and size_t are 32-bit, if you use 64-bit-wide variable
in the loop, you could end up with loop exit count being of the type
wider than the size_t. Now, i'm not sure if we can produce `bcmp`
from that (just truncate?), but we certainly should not assert/miscompile.
Modified:
llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
llvm/trunk/test/Transforms/LoopIdiom/bcmp-basic.ll
Modified: llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp?rev=374811&r1=374810&r2=374811&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp Mon Oct 14 12:46:34 2019
@@ -2080,6 +2080,10 @@ bool LoopIdiomRecognize::recognizeBCmpLo
LLVM_DEBUG(dbgs() << "SCEV expressions for loads are acceptable.\n");
+ // bcmp / memcmp take length argument as size_t, so let's conservatively
+ // assume that the iteration count should be not wider than that.
+ Type *CmpFuncSizeTy = DL->getIntPtrType(SE->getContext());
+
// For how many iterations is loop guaranteed not to exit via LoopLatch?
// This is one less than the maximal number of comparisons,and is: n + -1
const SCEV *LoopExitCount =
@@ -2089,6 +2093,8 @@ bool LoopIdiomRecognize::recognizeBCmpLo
// Exit count, similarly, must be loop-invant that dominates the loop header.
if (LoopExitCount == SE->getCouldNotCompute() ||
!LoopExitCount->getType()->isIntOrPtrTy() ||
+ LoopExitCount->getType()->getScalarSizeInBits() >
+ CmpFuncSizeTy->getScalarSizeInBits() ||
!SE->isAvailableAtLoopEntry(LoopExitCount, CurLoop)) {
LLVM_DEBUG(dbgs() << "Unsupported SCEV expression for loop latch exit.\n");
return false;
Modified: llvm/trunk/test/Transforms/LoopIdiom/bcmp-basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopIdiom/bcmp-basic.ll?rev=374811&r1=374810&r2=374811&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopIdiom/bcmp-basic.ll (original)
+++ llvm/trunk/test/Transforms/LoopIdiom/bcmp-basic.ll Mon Oct 14 12:46:34 2019
@@ -1758,3 +1758,62 @@ cleanup:
%res = phi i1 [ false, %for.body ], [ true, %for.cond ], [ false, %entry ]
ret i1 %res
}
+
+; With -m32:
+; int index_wider_than_pointer(int* a, int* b, long long num) {
+; for(long long i = 0; i < num; ++i) {
+; if(a[i] != b[i])
+; return 1;
+; }
+; return 0;
+; }
+define dso_local i64 @test(i64* %a, i64* %b, i128 %num) {
+; CHECK-LABEL: @test(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP9:%.*]] = icmp sgt i128 [[NUM:%.*]], 0
+; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY_PREHEADER:%.*]], label [[CLEANUP:%.*]]
+; CHECK: for.body.preheader:
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.cond:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i128 [[INC:%.*]], [[NUM]]
+; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[CLEANUP_LOOPEXIT:%.*]]
+; CHECK: for.body:
+; CHECK-NEXT: [[I_010:%.*]] = phi i128 [ [[INC]], [[FOR_COND:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
+; CHECK-NEXT: [[IDXPROM:%.*]] = trunc i128 [[I_010]] to i64
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[A:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[ARRAYIDX]]
+; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i64, i64* [[B:%.*]], i64 [[IDXPROM]]
+; CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[ARRAYIDX2]]
+; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i64 [[TMP0]], [[TMP1]]
+; CHECK-NEXT: [[INC]] = add nuw nsw i128 [[I_010]], 1
+; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND]], label [[CLEANUP_LOOPEXIT]]
+; CHECK: cleanup.loopexit:
+; CHECK-NEXT: [[DOTPH:%.*]] = phi i64 [ 1, [[FOR_BODY]] ], [ 0, [[FOR_COND]] ]
+; CHECK-NEXT: br label [[CLEANUP]]
+; CHECK: cleanup:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[DOTPH]], [[CLEANUP_LOOPEXIT]] ]
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+entry:
+ %cmp9 = icmp sgt i128 %num, 0
+ br i1 %cmp9, label %for.body, label %cleanup
+
+for.cond: ; preds = %for.body
+ %cmp = icmp slt i128 %inc, %num
+ br i1 %cmp, label %for.body, label %cleanup
+
+for.body: ; preds = %entry, %for.cond
+ %i.010 = phi i128 [ %inc, %for.cond ], [ 0, %entry ]
+ %idxprom = trunc i128 %i.010 to i64
+ %arrayidx = getelementptr inbounds i64, i64* %a, i64 %idxprom
+ %0 = load i64, i64* %arrayidx
+ %arrayidx2 = getelementptr inbounds i64, i64* %b, i64 %idxprom
+ %1 = load i64, i64* %arrayidx2
+ %cmp3 = icmp eq i64 %0, %1
+ %inc = add nuw nsw i128 %i.010, 1
+ br i1 %cmp3, label %for.cond, label %cleanup
+
+cleanup: ; preds = %for.body, %for.cond, %entry
+ %2 = phi i64 [ 0, %entry ], [ 0, %for.cond ], [ 1, %for.body ]
+ ret i64 %2
+}
More information about the llvm-commits
mailing list