<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Missed optimization leading to inability to remove bounds check"
   href="https://bugs.llvm.org/show_bug.cgi?id=49885">49885</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Missed optimization leading to inability to remove bounds check
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>new-bugs
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>new bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>alex.gaynor@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>(All content available as godbolt: <a href="https://godbolt.org/z/s6deqs71h">https://godbolt.org/z/s6deqs71h</a>)

Given the following code, llvm should be able to prove that the bounds checks
within the loop are never necessary:

#include <cassert>
#include <cstdint>
#include <cstddef>
#include <vector>

uint64_t f(std::vector<uint64_t>& data, size_t start, size_t end){
    assert(start < end && start < data.size() && end <= data.size());

    uint64_t total = 0;
    for (size_t i = start; i < end; i++) {
        total += data.at(i);
    }
    return total;
}

However the following code is generated:

f(std::vector<unsigned long, std::allocator<unsigned long> >&, unsigned long,
unsigned long):               # @f(std::vector<unsigned long,
std::allocator<unsigned long> >&, unsigned long, unsigned long)
        push    rax
        cmp     rsi, rdx
        jae     .LBB0_6
        mov     r9, qword ptr [rdi]
        mov     r10, qword ptr [rdi + 8]
        mov     rax, r10
        sub     rax, r9
        mov     r8, rax
        sar     r8, 3
        cmp     r8, rsi
        jbe     .LBB0_6
        cmp     r8, rdx
        jb      .LBB0_6
        test    rax, rax
        mov     rcx, -1
        cmovns  rcx, rax
        test    rcx, rcx
        mov     edi, 1
        cmovle  rdi, rcx
        mov     rcx, r9
        sub     rcx, r10
        cmp     rcx, rax
        cmovle  rcx, rax
        shr     rcx, 3
        imul    rcx, rdi
        cmp     rsi, rcx
        cmova   rcx, rsi
        xor     eax, eax
.LBB0_4:                                # =>This Inner Loop Header: Depth=1
        cmp     rcx, rsi
        je      .LBB0_5
        add     rax, qword ptr [r9 + 8*rsi]
        add     rsi, 1
        cmp     rdx, rsi
        jne     .LBB0_4
        pop     rcx
        ret
.LBB0_5:
        mov     edi, offset .L.str.2
        mov     rsi, rcx
        mov     rdx, r8
        xor     eax, eax
        call    std::__throw_out_of_range_fmt(char const*, ...)
.LBB0_6:
        mov     edi, offset .L.str
        mov     esi, offset .L.str.1
        mov     ecx, offset .L__PRETTY_FUNCTION__.f(std::vector<unsigned long,
std::allocator<unsigned long> >&, unsigned long, unsigned long)
        mov     edx, 7
        call    __assert_fail
.L.str:
        .asciz  "start < end && start < data.size() && end <= data.size()"

.L.str.1:
        .asciz  "/app/example.cpp"

.L__PRETTY_FUNCTION__.f(std::vector<unsigned long, std::allocator<unsigned
long> >&, unsigned long, unsigned long):
        .asciz  "uint64_t f(std::vector<uint64_t> &, size_t, size_t)"

.L.str.2:
        .asciz  "vector::_M_range_check: __n (which is %zu) >= this->size()
(which is %zu)"



The throw_out_of_range exception code should be able to be optimized out.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>