[InstCombine] Require equal source element type in icmp of gep fold

Without opaque pointers, this is implicitly enforced. This previously
resulted in a miscompile.
This commit is contained in:
Nikita Popov 2022-02-11 09:38:28 +01:00
parent c28b0b9d18
commit 3571bdb4f3
2 changed files with 26 additions and 1 deletions

View File

@ -950,7 +950,8 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
return foldGEPICmp(GEPLHS, GEPRHS->getOperand(0), Cond, I);
bool GEPsInBounds = GEPLHS->isInBounds() && GEPRHS->isInBounds();
if (GEPLHS->getNumOperands() == GEPRHS->getNumOperands()) {
if (GEPLHS->getNumOperands() == GEPRHS->getNumOperands() &&
GEPLHS->getSourceElementType() == GEPRHS->getSourceElementType()) {
// If the GEPs only differ by one index, compare it.
unsigned NumDifferences = 0; // Keep track of # differences.
unsigned DiffOperand = 0; // The operand that differs.

View File

@ -281,3 +281,27 @@ define ptr addrspace(1) @gep_of_addrspace_cast(ptr %ptr) {
%gep = getelementptr inbounds i32, ptr addrspace(1) %cast1, i64 1
ret ptr addrspace(1) %gep
}
define i1 @cmp_gep_same_base_same_type(ptr %ptr, i64 %idx1, i64 %idx2) {
; CHECK-LABEL: @cmp_gep_same_base_same_type(
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[IDX1:%.*]], [[IDX2:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%gep1 = getelementptr inbounds i32, ptr %ptr, i64 %idx1
%gep2 = getelementptr inbounds i32, ptr %ptr, i64 %idx2
%cmp = icmp ult ptr %gep1, %gep2
ret i1 %cmp
}
define i1 @cmp_gep_same_base_different_type(ptr %ptr, i64 %idx1, i64 %idx2) {
; CHECK-LABEL: @cmp_gep_same_base_different_type(
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[IDX1:%.*]], 2
; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nsw i64 [[IDX2:%.*]], 3
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%gep1 = getelementptr inbounds i32, ptr %ptr, i64 %idx1
%gep2 = getelementptr inbounds i64, ptr %ptr, i64 %idx2
%cmp = icmp ult ptr %gep1, %gep2
ret i1 %cmp
}