Skip to content

riscv64: Use Constant Pool to load 32 and 64 bit constants#5578

Closed
afonso360 wants to merge 2 commits intobytecodealliance:mainfrom
afonso360:fix-riscv64-imm
Closed

riscv64: Use Constant Pool to load 32 and 64 bit constants#5578
afonso360 wants to merge 2 commits intobytecodealliance:mainfrom
afonso360:fix-riscv64-imm

Conversation

@afonso360
Copy link
Contributor

👋 Hey,

This PR switches the riscv64 backend to use the constant pool for loading 32 and 64 bit constants. We only do this in the case where we can't simply use a lui / addi instruction to get the right constant.

It also adds a Label based addressing mode for loads and stores.

Fixes #5569

My understanding of this issue is that a veneer would be emitted right in the middle of a LoadConst sequence and since we used hardcoded relative offsets, these would break and point to the wrong location. Switching to a label based system prevents this kinds of issues.

@github-actions github-actions bot added the cranelift Issues related to the Cranelift code generator label Jan 16, 2023
@afonso360 afonso360 changed the title cranelift: Use Constant Pool to load 32 and 64 bit constants riscv64: Use Constant Pool to load 32 and 64 bit constants Jan 16, 2023
let data = imm.to_le_bytes();

// Emit the constant into the pool
sink.defer_constant(label_data, 4, &data[..], u32::MAX);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use a constant pool for 32bit values? Loading from the constant pool requires auipc+lw while loading a constant requires lui+addiw which is exactly the same size in terms of instructions but doesn't require an extra 4 bytes for the constant pool entry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do try to use lui+addi in Inst::load_constant_u32 and fall back here if those for some reason can't load it. Although I'm not entirely sure if that ever happens.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That shouldn't be possible. 20 for lui + 12 for addiw == 32.

Copy link
Contributor Author

@afonso360 afonso360 Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right, and I think that just found a bug with our constant emissions, I tried to assert that we would always emit lui+addiw and that assert failed! I'm going to investigate further, but yeah removing the LoadConst32 instruction seems like the way to go.


; block0:
; auipc a0,0; ld a0,12(a0); j 12; .8byte 0xffff00000000
; auipc a0,.LConst; ld a0,.LConst(0xffff00000000)
Copy link
Contributor

@bjorn3 bjorn3 Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This label doesn't distinguish between two different constants, right? Or do I read it wrong?

Copy link
Contributor Author

@afonso360 afonso360 Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really have a very good solution for this, we only know which label we get assigned after we emit the constant into the pool, and that only happens at emit time. When formatting the code we don't know which one its going to end up in.

Edit: Also, this label is not the actual label that ends up being used, this is sort of our internal assembly which for some ops is not real riscv assembly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, the actual immediate is put between parens. I read the parens as being part of the regular lw inst syntax, but in that case it would be more like lw x2, 0xdeadbeef(x1), so my brain still parsed it wrong.

Copy link
Contributor Author

@afonso360 afonso360 Jan 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that riscv has li rd, imm assembler mnemonic that is much more readable. I've switched to using that.

@afonso360 afonso360 marked this pull request as draft January 19, 2023 09:12
@cfallin
Copy link
Member

cfallin commented Feb 8, 2023

@afonso360 it looks like the linked issue (#5569) has been resolved another way; do you still think you want to pursue this PR?

@afonso360
Copy link
Contributor Author

I still think it would be a worthwhile improvement to the RISCV backend, however I don't really have time to work on this right now. I'll send a new PR once It's ready to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cranelift Issues related to the Cranelift code generator

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cranelift: Illegal instruction on riscv64

3 participants