Value *Op0, *Op1;
ConstantInt *CI;
+ // Handle the (gep (gep ....), C) case by incrementing the constant
+ // coefficient of the inner GEP, if C is a constant.
+ auto *InnerGEP = dyn_cast<GetElementPtrInst>(GEP->getPointerOperand());
+ if (InnerGEP && InnerGEP->getNumOperands() == 2 &&
+ isa<ConstantInt>(GEP->getOperand(1))) {
+ APInt Offset = cast<ConstantInt>(GEP->getOperand(1))->getValue();
+ auto Result = decompose(InnerGEP, Preconditions, IsSigned);
+ Result[0].Coefficient += Offset.getSExtValue();
+ if (Offset.isNegative()) {
+ // Add pre-condition ensuring the GEP is increasing monotonically and
+ // can be de-composed.
+ Preconditions.emplace_back(
+ CmpInst::ICMP_SGE, InnerGEP->getOperand(1),
+ ConstantInt::get(InnerGEP->getOperand(1)->getType(),
+ -1 * Offset.getSExtValue()));
+ }
+ return Result;
+ }
+
// If the index is zero-extended, it is guaranteed to be positive.
if (match(GEP->getOperand(GEP->getNumOperands() - 1),
m_ZExt(m_Value(Op0)))) {
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
; CHECK-NEXT: [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 3
; CHECK-NEXT: [[CMP_ADD_4:%.*]] = icmp uge ptr [[DST_ADD_4]], [[LOWER]]
-; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_ADD_4]]
+; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true
; CHECK-NEXT: ret i1 [[RES_2]]
;
%pre = icmp uge ptr %dst, %lower
; CHECK-NEXT: [[CMP_ADD_3:%.*]] = icmp ult ptr [[DST_ADD_3]], [[UPPER]]
; CHECK-NEXT: [[DST_ADD_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_1]], i64 3
; CHECK-NEXT: [[CMP_ADD_4:%.*]] = icmp ult ptr [[DST_ADD_4]], [[UPPER]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_ADD_3]], [[CMP_ADD_4]]
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
; CHECK-NEXT: [[DST_ADD_5:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_1]], i64 4
; CHECK-NEXT: [[CMP_ADD_5:%.*]] = icmp ult ptr [[DST_ADD_5]], [[UPPER]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_ADD_5]]
; CHECK-NEXT: [[CMP_ADD_1:%.*]] = icmp ule ptr [[DST_ADD_1]], [[UPPER]]
; CHECK-NEXT: [[DST_ADD_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 2
; CHECK-NEXT: [[CMP_ADD_2:%.*]] = icmp ule ptr [[DST_ADD_2]], [[UPPER]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_ADD_1]], [[CMP_ADD_2]]
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[CMP_ADD_2]]
; CHECK-NEXT: ret i1 [[RES_1]]
;
%not.zero = icmp ne i8 %idx, 0
; CHECK-NEXT: [[CMP_ADD_1:%.*]] = icmp ule ptr [[DST_ADD_1]], [[UPPER]]
; CHECK-NEXT: [[DST_ADD_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 2
; CHECK-NEXT: [[CMP_ADD_2:%.*]] = icmp ule ptr [[DST_ADD_2]], [[UPPER]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_ADD_1]], [[CMP_ADD_2]]
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, [[CMP_ADD_2]]
; CHECK-NEXT: ret i1 [[RES_1]]
;
%sgt.1 = icmp sgt i8 %idx, 1
; CHECK-NEXT: [[CMP_IDX_1:%.*]] = icmp ult ptr [[DST_ADD_IDX_1]], [[UPPER]]
; CHECK-NEXT: [[DST_ADD_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 2
; CHECK-NEXT: [[CMP_IDX_2:%.*]] = icmp ult ptr [[DST_ADD_IDX_2]], [[UPPER]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_IDX_1]], [[CMP_IDX_2]]
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
; CHECK-NEXT: [[DST_ADD_IDX_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_IDX]], i64 3
; CHECK-NEXT: [[CMP_IDX_3:%.*]] = icmp ult ptr [[DST_ADD_IDX_3]], [[UPPER]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_IDX_3]]
; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp uge ptr [[DST_SUB_1]], [[LOWER]]
; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3
; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp uge ptr [[DST_SUB_3]], [[LOWER]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]]
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
; CHECK-NEXT: [[DST_SUB_4:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -4
; CHECK-NEXT: [[CMP_SUB_4:%.*]] = icmp uge ptr [[DST_SUB_4]], [[LOWER]]
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[CMP_SUB_4]]
; CHECK-NEXT: [[CMP_SUB_1:%.*]] = icmp ult ptr [[DST_SUB_1]], [[UPPER]]
; CHECK-NEXT: [[DST_SUB_3:%.*]] = getelementptr inbounds i8, ptr [[DST_ADD_3]], i64 -3
; CHECK-NEXT: [[CMP_SUB_3:%.*]] = icmp ult ptr [[DST_SUB_3]], [[UPPER]]
-; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[CMP_SUB_1]], [[CMP_SUB_3]]
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true
; CHECK-NEXT: ret i1 [[RES_1]]
;
%dst.add.4 = getelementptr inbounds i8, ptr %dst, i64 4