diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -288,8 +288,20 @@ // Emitting 'icmp eq Idx, 0' isn't correct in this case because the // comparison is false if Idx was 0x80..00. // We need to erase the highest countTrailingZeros(ElementSize) bits of Idx. - if (countTrailingZeros(ElementSize) != 0) { - Value *Mask = ConstantInt::getSigned(Idx->getType(), -1); + // Unnecessary 'lshr' and 'and' can cause infinite loops, it is added only + // when overflow can occur. + Value *IdxBeforeSext; + bool IsOverflows = false; + if (match(Idx, m_SExt(m_Value(IdxBeforeSext)))) + IsOverflows = + IdxBeforeSext->getType()->getPrimitiveSizeInBits().getFixedSize() >= + PtrSize; + else + IsOverflows = + Idx->getType()->getPrimitiveSizeInBits().getFixedSize() >= PtrSize; + + if (IsOverflows && countTrailingZeros(ElementSize) != 0) { + Value *Mask = ConstantInt::get(Idx->getType(), -1); Mask = Builder.CreateLShr(Mask, countTrailingZeros(ElementSize)); Idx = Builder.CreateAnd(Idx, Mask); } diff --git a/llvm/test/Transforms/InstCombine/load-cmp.ll b/llvm/test/Transforms/InstCombine/load-cmp.ll --- a/llvm/test/Transforms/InstCombine/load-cmp.ll +++ b/llvm/test/Transforms/InstCombine/load-cmp.ll @@ -300,9 +300,7 @@ define i1 @test10_struct_arr_noinbounds_i16(i16 %x) { ; CHECK-LABEL: @test10_struct_arr_noinbounds_i16( -; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[X:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 268435455 -; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP2]], 1 +; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[X:%.*]], 1 ; CHECK-NEXT: ret i1 [[R]] ; %p = getelementptr [4 x %Foo], [4 x %Foo]* @GStructArr, i32 0, i16 %x, i32 2