Test: Transforms/ConstraintElimination/gep-arithmetic.ll The optimization below is incorrect as it misses one case: lower < src.end < src < upper < src.step define i4 @ptr_N_signed_positive_assume(* %src, * %lower, * %upper, i16 %N, i16 %step) { %entry: %src.end = gep inbounds * %src, 1 x i16 %N %cmp.src.start = icmp ult * %src, %lower %cmp.src.end = icmp uge * %src.end, %upper %N.neg = icmp slt i16 %N, 0 assume i1 %N.neg %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end br i1 %or.precond.0, label %trap.bb, label %step.check %step.check: %step.pos = icmp uge i16 %step, 0 %step.ult.N = icmp ult i16 %step, %N %and.step = and i1 %step.pos, %step.ult.N br i1 %and.step, label %ptr.check, label %exit %ptr.check: %src.step = gep inbounds * %src, 1 x i16 %step %cmp.step.start = icmp ult * %src.step, %lower %cmp.step.end = icmp uge * %src.step, %upper %or.check = or i1 %cmp.step.start, %cmp.step.end br i1 %or.check, label %trap.bb, label %exit %exit: ret i4 3 %trap.bb: ret i4 2 } => define i4 @ptr_N_signed_positive_assume(* %src, * %lower, * %upper, i16 %N, i16 %step) { %entry: %src.end = gep inbounds * %src, 1 x i16 %N %cmp.src.start = icmp ult * %src, %lower %cmp.src.end = icmp uge * %src.end, %upper %N.neg = icmp slt i16 %N, 0 assume i1 %N.neg %or.precond.0 = or i1 %cmp.src.start, %cmp.src.end br i1 %or.precond.0, label %trap.bb, label %step.check %step.check: %step.pos = icmp uge i16 %step, 0 %step.ult.N = icmp ult i16 %step, %N %and.step = and i1 %step.pos, %step.ult.N br i1 %and.step, label %ptr.check, label %exit %ptr.check: %src.step = gep inbounds * %src, 1 x i16 %step %cmp.step.start = icmp ult * %src.step, %lower %cmp.step.end = icmp uge * %src.step, %upper %or.check = or i1 0, 0 br i1 %or.check, label %trap.bb, label %exit %exit: ret i4 3 %trap.bb: ret i4 2 } Transformation doesn't verify! ERROR: Value mismatch Example: * %src = pointer(non-local, block_id=1, offset=229377) * %lower = pointer(non-local, block_id=0, offset=-393217) * %upper = pointer(non-local, block_id=0, offset=-419450) i16 %N = #x9014 (36884, -28652) i16 %step = #x100d (4109) Source: * %src.end = pointer(non-local, block_id=1, offset=200725) i1 %cmp.src.start = #x0 (0) i1 %cmp.src.end = #x0 (0) i1 %N.neg = #x1 (1) i1 %or.precond.0 = #x0 (0) i1 %step.pos = #x1 (1) i1 %step.ult.N = #x1 (1) i1 %and.step = #x1 (1) * %src.step = pointer(non-local, block_id=1, offset=233486) i1 %cmp.step.start = #x0 (0) i1 %cmp.step.end = #x1 (1) i1 %or.check = #x1 (1) SOURCE MEMORY STATE =================== NON-LOCAL BLOCKS: Block 0 > size: 0 align: 1 alloc type: 0 address: 0 Block 1 > size: 524288 align: 4 alloc type: 0 address: 425988 Block 2 > size: 100654 align: 8589934592 alloc type: 0 address: 263504 Block 3 > size: 230832 align: 8589934592 alloc type: 0 address: 29184 Target: * %src.end = pointer(non-local, block_id=1, offset=200725) i1 %cmp.src.start = #x0 (0) i1 %cmp.src.end = #x0 (0) i1 %N.neg = #x1 (1) i1 %or.precond.0 = #x0 (0) i1 %step.pos = #x1 (1) i1 %step.ult.N = #x1 (1) i1 %and.step = #x1 (1) * %src.step = pointer(non-local, block_id=1, offset=233486) i1 %cmp.step.start = #x0 (0) i1 %cmp.step.end = #x1 (1) i1 %or.check = #x0 (0) Source value: #x2 (2) Target value: #x3 (3)