Signed comparison of pointers must compare underlying addrs
ADD
tests/alive-tv/ptrcmp/slt.srctgt.ll
+define i1 @src(i8* %ptr) {
+entry:
+ %first1 = getelementptr inbounds i8, i8* %ptr, i32 0
+ %last1 = getelementptr inbounds i8, i8* %ptr, i32 42
+ %cmp = icmp slt i8* %first1, %last1
+ ret i1 %cmp
+}
+
+define i1 @tgt(i8* %ptr) {
+entry:
+ %first1 = getelementptr inbounds i8, i8* %ptr, i32 0
+ %last1 = getelementptr i8, i8* %ptr, i32 42
+ %cmp = icmp slt i8* %first1, %last1
+ ret i1 %cmp
+}

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -1342,6 +1342,8 @@ static void optimize_ptrcmp(Function &f) {
auto cond = icmp->getCond();
bool is_eq = cond == ICmp::EQ || cond == ICmp::NE;
+ bool is_signed_cmp = cond == ICmp::SLE || cond == ICmp::SLT ||
+ cond == ICmp::SGE || cond == ICmp::SGT;
auto ops = icmp->operands();
auto *op0 = ops[0];
@@ -1358,7 +1360,10 @@ static void optimize_ptrcmp(Function &f) {
if (base0 && base0 == base1) {
if (is_eq)
const_cast<ICmp*>(icmp)->setPtrCmpMode(ICmp::PROVENANCE);
- else if (is_inbounds(*op0) && is_inbounds(*op1))
+ else if (is_inbounds(*op0) && is_inbounds(*op1) && !is_signed_cmp)
+ // Even if op0 and op1 are inbounds, 'icmp slt op0, op1' must
+ // compare underlying addresses because it is possible for the block
+ // to span across [a, b] where a >s 0 && b <s 0.
const_cast<ICmp*>(icmp)->setPtrCmpMode(ICmp::OFFSETONLY);
}
}

Signed comparison of pointers must compare underlying addrs (#765)