For inline asm with memory operands, we can merge the offset into
the second operand of memory constraint operands.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
There is a problem here, can someone explain it?
For LLVM IR:
reduced.ll
@g = external global [4000 x i32], align 4 define void @test() nounwind { call void asm "sw zero, $0", "=*m"(ptr elementtype(i32) @g) ret void }
llc -code-model=medium -no-integrated-as reduced.ll
test: # @test # %bb.0: .Lpcrel_hi0: auipc a0, %pcrel_hi(g) #APP sw zero, %pcrel_lo(.Lpcrel_hi0)(a0) #NO_APP ret
llc -code-model=medium reduced.ll
test: # @test # %bb.0: .Lpcrel_hi0: auipc a0, %pcrel_hi(g) #APP sw zero, %pcrel_lo(.Lpcrel_hi00)(a0) #NO_APP ret
The difference is that there is an extra 0 after .Lpcrel_hi when there is no -no-integrated-as.
Is this a bug or a feature by design?
llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp | ||
---|---|---|
467 | Can we use MachineOperand::ChangeToGA and MachineOperand::ChangeToMCSymbol to avoid building a new instruction? |
llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp | ||
---|---|---|
467 | Though I guess we would also need ChangeToCPI for constant pool? |
- Add INLINEASM_BR.
- Use changeToXXX to update operands instead of creating new MI.
- Record indexes of each inline asm MI.
llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp | ||
---|---|---|
467 | There are four cases of using RISCVTargetLowering::getAddr: GlobalAddress, BlockAddress, ConstantPool and JumpTable. |
@samitolvanen is reporting that this is causing breakage for us in the Linux kernel: https://github.com/ClangBuiltLinux/linux/issues/1928.
Please consider whether this can be fixed forward quickly, or should be reverted. Otherwise I will revert shortly.
I think the problem is that atomic instructions don't have an immediate offset field so they are different than other instructions. I'm not sure we can generically do this patch for the "m" constraint. We should revert.
Doing it for m is fine. What's not fine is doing it for A, as used by Linux in the reported errors, which presumably presents itself close enough to m to not be caught by the code here. Presumably we need a constraint_A_with_global_1 test to catch this.
llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp | ||
---|---|---|
467 | You can absolutely get a BlockAddress in IR, and that's exposed to C for the GNU indirect goto &&label syntax. You have to write some very cursed C (something like "m"(*(void **)&&label)) to end up with it in an m constraint, but it's technically possible to write, and so that input will now hit this report_fatal_error. |
Sorry for the revert, but I've left two reduced test cases in https://github.com/ClangBuiltLinux/linux/issues/1928. My hope is that those can help you reland this work.
Ah, good eye! That appeared in both reproducers linked above. Thanks for taking the time to analyze this and for your quick feedback @jrtc27 and @craig.topper .
This is unused now.