CodeGen Prepare address mode sinking strips `nusw` from GEPs
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Reproduction on goldbolt: [link](https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:llvm,selection:(endColumn:2,endLineNumber:21,positionColumn:1,positionLineNumber:1,selectionStartColumn:2,selectionStartLineNumber:21,startColumn:1,startLineNumber:1),source:'target+datalayout+%3D+%22e-m:e-p:32:32-i64:64-n32:64-S128%22%0Atarget+triple+%3D+%22wasm32-unknown-emscripten%22%0A%0Adeclare+void+@consume(ptr)%0A%0Adefine+i32+@TestMethod(ptr+%25l0,+ptr+%25l1,+ptr+%25l2)+%7B%0ABB00:%0A++%25l19+%3D+getelementptr+nusw+i8,+ptr+%25l0,+i32+40%0A++%25ld+%3D+load+ptr,+ptr+%25l19%0A++call+void+@consume(ptr+%25ld)%0A++%25l20+%3D+icmp+eq+ptr+%25l1,+null%0A++br+i1+%25l20,+label+%25BBTH,+label+%25BB01%0A%0ABB01:%0A++%25l42+%3D+load+i32,+ptr+%25l19,+align+4%0A++ret+i32+%25l42%0A%0ABBTH:%0A++call+void+@consume(ptr+null)%0A++unreachable%0A%7D'),l:'5',n:'0',o:'LLVM+IR+source+%231',t:'0')),k:49.88577080976944,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:irclangtrunk,filters:(b:'0',binary:'1',binaryObject:'1',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1',verboseDemangling:'0'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:llvm,libs:!(),options:'-O2+-target+wasm32-unknown-emscripten+-mllvm+-print-after-all',overrides:!(),selection:(endColumn:21,endLineNumber:18,positionColumn:1,positionLineNumber:1,selectionStartColumn:21,selectionStartLineNumber:18,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+clang+(trunk)+(Editor+%231)',t:'0')),k:50.114229190230574,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4).
IR:
```llvm
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-emscripten"
declare void @consume(ptr)
define i32 @TestMethod(ptr %l0, ptr %l1, ptr %l2) {
BB00:
%l19 = getelementptr nusw i8, ptr %l0, i32 40
%ld = load ptr, ptr %l19
call void @consume(ptr %ld)
%l20 = icmp eq ptr %l1, null
br i1 %l20, label %BBTH, label %BB01
BB01:
%l42 = load i32, ptr %l19, align 4
ret i32 %l42
BBTH:
call void @consume(ptr null)
unreachable
}
```
```
> clang -c -O2 -target wasm32-unknown-emscripten test.ll
```
Output:
```wasm
TestMethod:
local.get 0
i32.load 40
call consume
block
local.get 1
i32.eqz
br_if 0
local.get 0
i32.const 40
i32.add
i32.load 0
return
end_block
i32.const 0
call consume
unreachable
end_function
```
Notice that we're not using address modes for second load. This is because the sinking loses `nusw`:
```llvm
BB00:
%l19 = getelementptr nusw nuw i8, ptr %l0, i32 40
%ld = load ptr, ptr %l19, align 4
tail call void @consume(ptr %ld)
%l20 = icmp eq ptr %l1, null
br i1 %l20, label %BBTH, label %BB01
BB01: ; preds = %BB00
%sunkaddr = getelementptr i8, ptr %l0, i32 40 ; The GEP of interest
%l42 = load i32, ptr %sunkaddr, align 4
ret i32 %l42
BBTH: ; preds = %BB00
tail call void @consume(ptr null)
unreachable
```
Contributor guide
Research direction
Start by running the provided clang command with the Goldbolt LLVM IR reproducer and compare the generated IR around the sunk GEP with the original nusw GEP. Trace CodeGen Prepare's address-mode sinking path to determine where the flag is dropped; done when the sunk GEP preserves the required flags and the second load can use the address mode.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100