void const_locs() {
  char *a = (char *)0x1000;
  char *b = (char *)0x1100;
start:
  clang_analyzer_eval(a != b);
  clang_analyzer_eval(a < b);
  clang_analyzer_eval(a <= b);
  clang_analyzer_eval((b - a) == 0x100);
  clang_analyzer_eval(&&start == a);
  clang_analyzer_eval(a == &&start);
  clang_analyzer_eval(&a == (char **)a);
  clang_analyzer_eval((char **)a == &a);
}


x86 assembly (clang, -O0):
<const_locs>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    $0x1000,%eax
mov    %rax,-0x8(%rbp)
mov    $0x1100,%eax
mov    %rax,-0x10(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x10(%rbp),%rcx
sub    %rcx,%rax
setne  %al
movzbl %al,%edi
xor    %eax,%eax
mov    %al,-0x19(%rbp)
call   1030 <clang_analyzer_eval@plt>
mov    -0x19(%rbp),%al
mov    -0x8(%rbp),%rcx
mov    -0x10(%rbp),%rdx
sub    %rdx,%rcx
setb   %cl
movzbl %cl,%edi
call   1030 <clang_analyzer_eval@plt>
mov    -0x19(%rbp),%al
mov    -0x8(%rbp),%rcx
mov    -0x10(%rbp),%rdx
sub    %rdx,%rcx
setbe  %cl
movzbl %cl,%edi
call   1030 <clang_analyzer_eval@plt>
mov    -0x19(%rbp),%al
mov    -0x10(%rbp),%rcx
mov    -0x8(%rbp),%rdx
sub    %rdx,%rcx
sub    $0x100,%rcx
sete   %cl
movzbl %cl,%edi
call   1030 <clang_analyzer_eval@plt>
mov    -0x19(%rbp),%al
mov    -0x8(%rbp),%rdx
lea    -0x7b(%rip),%rcx
mov    %rcx,-0x18(%rbp)
sub    %rdx,%rcx
sete   %cl
movzbl %cl,%edi
call   1030 <clang_analyzer_eval@plt>
mov    -0x18(%rbp),%rcx
mov    -0x8(%rbp),%rax
sub    %rcx,%rax
sete   %al
and    $0x1,%al
movzbl %al,%edi
mov    $0x0,%al
call   1030 <clang_analyzer_eval@plt>
mov    -0x8(%rbp),%rcx
lea    -0x8(%rbp),%rax
cmp    %rcx,%rax
sete   %al
and    $0x1,%al
movzbl %al,%edi
mov    $0x0,%al
call   1030 <clang_analyzer_eval@plt>
mov    -0x8(%rbp),%rax
lea    -0x8(%rbp),%rcx
cmp    %rcx,%rax
sete   %al
and    $0x1,%al
movzbl %al,%edi
mov    $0x0,%al
call   1030 <clang_analyzer_eval@plt>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<const_locs>:
push   %rbx
sub    $0x10,%rsp
movq   $0x1000,0x8(%rsp)
mov    $0x1,%edi
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
mov    $0x1,%edi
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
mov    $0x1,%edi
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
mov    $0x1,%edi
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
lea    -0x37(%rip),%rax
xor    %ebx,%ebx
cmp    $0x1000,%rax
sete   %bl
mov    %ebx,%edi
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
mov    %ebx,%edi
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
lea    0x8(%rsp),%rbx
xor    %edi,%edi
cmp    $0x1000,%rbx
sete   %dil
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
xor    %edi,%edi
cmp    %rbx,0x8(%rsp)
sete   %dil
xor    %eax,%eax
call   1030 <clang_analyzer_eval@plt>
add    $0x10,%rsp
pop    %rbx
ret

LLVM IR (-O0):
define void @const_locs() {
%1 = alloca i8*
%2 = alloca i8*
store i8* inttoptr (i64 4096 to i8*), i8** %1
store i8* inttoptr (i64 4352 to i8*), i8** %2
br label %3
3: ; preds = %45, %45, %0
%4 = load i8*, i8** %1
%5 = load i8*, i8** %2
%6 = icmp ne i8* %4, %5
%7 = zext i1 %6 to i32
%8 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %7)
%9 = load i8*, i8** %1
%10 = load i8*, i8** %2
%11 = icmp ult i8* %9, %10
%12 = zext i1 %11 to i32
%13 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %12)
%14 = load i8*, i8** %1
%15 = load i8*, i8** %2
%16 = icmp ule i8* %14, %15
%17 = zext i1 %16 to i32
%18 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %17)
%19 = load i8*, i8** %2
%20 = load i8*, i8** %1
%21 = ptrtoint i8* %19 to i64
%22 = ptrtoint i8* %20 to i64
%23 = sub i64 %21, %22
%24 = icmp eq i64 %23, 256
%25 = zext i1 %24 to i32
%26 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %25)
%27 = load i8*, i8** %1
%28 = icmp eq i8* blockaddress(@const_locs, %3), %27
%29 = zext i1 %28 to i32
%30 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %29)
%31 = load i8*, i8** %1
%32 = icmp eq i8* %31, blockaddress(@const_locs, %3)
%33 = zext i1 %32 to i32
%34 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %33)
%35 = load i8*, i8** %1
%36 = bitcast i8* %35 to i8**
%37 = icmp eq i8** %1, %36
%38 = zext i1 %37 to i32
%39 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %38)
%40 = load i8*, i8** %1
%41 = bitcast i8* %40 to i8**
%42 = icmp eq i8** %41, %1
%43 = zext i1 %42 to i32
%44 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %43)
ret void
45: ; No predecessors!
indirectbr i8* undef, [label %3, label %3]
}

LLVM IR (-O2):
define void @const_locs() {
%1 = alloca i8*
%2 = bitcast i8** %1 to i8*
store i8* inttoptr (i64 4096 to i8*), i8** %1
br label %3
3: ; preds = %0
%4 = tail call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 1)
%5 = tail call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 1)
%6 = tail call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 1)
%7 = tail call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 1)
%8 = tail call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 zext (i1 icmp eq (i8* inttoptr (i64 4096 to i8*), i8* blockaddress(@const_locs, %3)) to i32))
%9 = tail call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 zext (i1 icmp eq (i8* inttoptr (i64 4096 to i8*), i8* blockaddress(@const_locs, %3)) to i32))
%10 = bitcast i8** %1 to i8***
%11 = icmp eq i8** %1, inttoptr (i64 4096 to i8**)
%12 = zext i1 %11 to i32
%13 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %12)
%14 = load i8**, i8*** %10
%15 = icmp eq i8** %14, %1
%16 = zext i1 %15 to i32
%17 = call i32 (i32, ...) bitcast (i32 (...)* @clang_analyzer_eval to i32 (i32, ...)*)(i32 %16)
ret void
}