Open coastalwhite opened 1 year ago
when we inspect the LLVM IR, it seems to assume that the numbers are i32s instead of u32s. Is this a problem with Rust's codegen output?
LLVM integers types do not differentiate between signed or unsigned integers. It's the operation (ie the intrinsic) that makes the differentiation and llvm.umax.*
is the unsigned max variant:
Return the smaller of %a and %b comparing the values as unsigned integers
It's seems to me that it's a problem with the RISC-V LLVM backend.
@rustbot labels: +A-LLVM +A-codegen +O-riscv +T-compiler -needs-triage
According to the documentation, for RV64, the registers are 64 bits wide. The arguments of the @llvm.umax.i32
intrinsic are 32 bits wide, and the higher 32 bits of the registers a0
and a1
are practically unknown. The maxu
instruction probably uses all of the 64 bits of the registers, so it is necessary to ensure that the higher 32 bits of the 64 bits wide registers have appropriate values, I would say.
The problem here is that we don't set signext
/zeroext
attributes on the arguments with the Rust ABI. signext is set when using extern "C"
(as it is an ABI requirement there). It probably makes sense to set them for the Rust ABI as well, for this target.
Codegen for
riscv64gc-unknown-linux-gnu
sends wrong type information to LLVM.When I compile on godbolt.org with the following flags.
GodBolt Link,l:'5',n:'0',o:'Rust+source+%231',t:'0')),k:49.165541155755804,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:r1710,deviceViewOpen:'1',filters:(b:'0',binary:'1',binaryObject:'1',commentOnly:'0',debugCalls:'1',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:rust,libs:!(),options:'--target%3Driscv64gc-unknown-linux-gnu+-C+target-feature%3D%2Bzbb+-C+opt-level%3D3',overrides:!(),selection:(endColumn:12,endLineNumber:5,positionColumn:1,positionLineNumber:1,selectionStartColumn:12,selectionStartLineNumber:5,startColumn:1,startLineNumber:1),source:1),l:'5',n:'0',o:'+rustc+1.71.0+(Editor+%231)',t:'0')),k:50.834458844244224,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4)
I tried this code:
It outputs:
It definitely does not need to sign extend
a0
ora1
and in fact, when we inspect the LLVM IR, it seems to assume that the numbers arei32
s instead ofu32
s. Is this a problem with Rust's codegen output?LLVM IR:
Properly optimized code would be: