<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/108010>108010</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [Clang] Constant value is corrupted when optimization is enabled
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          gerekon
      </td>
    </tr>
</table>

<pre>
    Hi guys!

I came across strange behavior. With enabled optimization when inlined function is provided with the address of external symbol (as argument) the two least bits of the constant used inside that function get cleared. Looks like optimizer assumes that address of external symbol should be aligned to 4-bytes and therefore aligns constatnt value used for bitwise `AND` operation with that address.
This is target independent behavior (checked this for X86, ARM and RISCV targets) because constant has aligned value already in IR.

Narrowed it down to simple program. IR can be generated with `clang --target=arm-none-eabi test.c -Og -S -emit-llvm`
After debugging it a bit I found that consntant changes its value when `test` function gets actually inlined at some step after `InstCombinePass` or `InlinerPass` optimization pass. Problem exists at any level of optimization except `-O0`.

Bad case C code 
```c
#define SOC_MMU_LINEAR_ADDR_MASK 0x1FFFFFF

extern int _instruction_reserved_end;

__attribute__((always_inline))
static inline unsigned int test(unsigned int vaddr)
{
    return vaddr & SOC_MMU_LINEAR_ADDR_MASK;
}
int main()
{
    // this produces inlined IR with wrongly aligned constant value 0x1FFFFFC
    volatile unsigned int tmp = test((unsigned int)&_instruction_reserved_end);
 return tmp;
}
```
IR for bad case. Note `%2 = and i32 ptrtoint (ptr @_instruction_reserved_end to i32), 33554428`
```
; Function Attrs: nofree norecurse nounwind memory(inaccessiblemem: readwrite)
define dso_local i32 @main() local_unnamed_addr #0 {
  %1 = alloca i32, align 4
  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %1)
  %2 = and i32 ptrtoint (ptr @_instruction_reserved_end to i32), 33554428
  store volatile i32 %2, ptr %1, align 4, !tbaa !4
  %3 = load volatile i32, ptr %1, align 4, !tbaa !4
  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %1)
  ret i32 %3
}
```
Good case C code 
```c
#define SOC_MMU_LINEAR_ADDR_MASK              0x1FFFFFF

extern int _instruction_reserved_end;

__attribute__((always_inline))
static inline unsigned int test(unsigned int vaddr)
{
    return vaddr & SOC_MMU_LINEAR_ADDR_MASK;
}

int main()
{
    // code below produces inlined IR with correct constant value 0x1FFFFFF
    volatile unsigned int addr = (unsigned int)&_instruction_reserved_end;
    volatile unsigned int tmp = test(addr);
    return tmp;
}
```
IR for good case. Note `%4 = and i32 %3, 33554431`
```
; Function Attrs: nofree norecurse nounwind memory(inaccessiblemem: readwrite)
define dso_local i32 @main() local_unnamed_addr #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %1)
  store volatile i32 ptrtoint (ptr @_instruction_reserved_end to i32), ptr %1, align 4, !tbaa !4
  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %2)
  %3 = load volatile i32, ptr %1, align 4, !tbaa !4
  %4 = and i32 %3, 33554431
  store volatile i32 %4, ptr %2, align 4, !tbaa !4
  %5 = load volatile i32, ptr %2, align 4, !tbaa !4
  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %2)
  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %1)
  ret i32 %5
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkWF1z4jYU_TXi5Q6MLdsEHnggUFqmm-wO6dcbI1sXo0aWPJIMob--I9l87W6ySZv2oWWYQIyv7rnnnns0MrNWlApxQrJbks17rHFbbSYlGnzUqpdrfpj8IKBsDpbQmERzEk3bv0soWIXACqOtBesMUyVCjlu2E9oM4FfhtoCK5RI56NqJSvzBnNAK9ltUIJQUCjlsGlWEq8JCbfROcOSw97Fui8A4N2gt6A3gk0OjmAR7qHItgdARs8BM2VSoHKHjEOD2GiQy6yAXLsT5q4VW1jHloLHIQSgrOILbMndOX6KDQiIzyAfwQetHC1I84hE5GmDWNhXaNu4FYHarG8khR2DSc8vBaUj7-cGhBaa4R2Rwo013g-3gOeVgx2SDLcqNNr6GvbAIZBhN7-dkGIGu0XQsthydsQzavvy0FdaT6ZjxNQnFsUbFUblTczx3xRaLR4_N3-5z_TYaEjqD6eougFwtH2a_dItYz26OBWvsBZdbT39XYYubSYOMH0AoWK4Gl2K5Z8bovefeAdd75Smxoqol-qaXhlUDWK6gYMrzVqLyVR6FQIZRIZkqod9v8ZBkzkzVV1phH1kuwKF1gwL6H0voP0AfK-H6Uu4qMoza_NONQwMc86YshSo9DObZhSVsdBN6wlwoTYXaiq1XswWvoba2IFoyjHwq34hL4VhghWuYlIeTrJkDqysE67AGFrKTYbRU1s10lQuFn5i1oaHdDz7MnC5ejkvNrB3AJ6NziRXgk7A-oQOmDiBxh9KL8CoCnwqsnV-3_zEiw-iqFbeMQ8EswgwKzRG634ZR-y66_2nCcSMUwsPH2fru7uf1h-X9d9PVejqfr9Z304cfIXqKF-F1uXo7DCCUg7VQ1pkmsLQ2aNHskK9RcZLcXoas18w5I_LG4XpN6MgPttyzg123ZBI69u9wrx8TUXQsQ6NsKz-fLjSGjq6u7fxonILJTZcXAMCga4xq7wBCh8_WeUZ7M2-_-JUrJlTA-rW1CV0QumhHqzaaN4WXUqeM5apV9d5oVcrDaYROc9Xq7cju7LzsTkvmhPy87qoGksyP9X9GQSBv-Hwr6PhU35ESV9Vf1nzSR2f-q9afOi0N4F67YFOEZjTA8R4iEgq1M057nISOameApNGzaLwriIQGzDNIkixLUzo6Jf0MA0luYXGcwqlzxpJkCkpvDCIobbBojPXfGrUXikOFlTYHQkdCsaJAa4UfKKx8lPetvREOTw3t1M-tXktdMBmKIWl0bjyE6-tGKVYhX3dCSiK40AKhWdzSIf3dbXWztueQHu8qmJSw04L7BN63BlJs0IkKB9Yx4wZ15GEPU0h9tKdRaaUaKUOCE-aQ793p75a2zu9YJw0GOmhGj4BaIOfS6AwIjV3OmP9MLwAmAaDUjF-t9saFXuAMFX89Y8bvkW0tycua_17rd3LOq9f_1kbfZqaB8Ryl3j9vqYU2Bgv3nJUuvmWlbRHJHN5oosntG036yGfyJZNvcN_yKMgr-02v5j_I-jTNSfzfN9OzBf47lvsVX_zrpvs-BviKCuj1pvE-nvxt9b24l6QX6ejr0mXfxP2ahf7OXnJJ5D-wJ2XPOUGPTxI-Tsash5P4hmbj4TijcW87yekNMhqPkptoU_DNaFMg0oxl8ZiyJLnJe2JCI5pG4ziK42yUxgOa39B8iCNMx3k85ClJI6yYkINQgjZlT1jb4CSORlEc9STLUdrwwIDScDAjlJJs3jMTH9DPm9L6-v055byEE06GpwyzEJHNYXbt0sIG_27qcO7zp62rM42wx4cJvcbIyda52ltUuzuUwm2bfFDoitBFOPi1H_3a6N-xcIQuQgmW0EVXxW5C_wwAAP__LLpCgA">