This is an archive of the discontinued LLVM Phabricator instance.

[mips] Clang generates unaligned offset for MSA instruction st.d
ClosedPublic

Authored by mamidzic on Apr 25 2016, 12:56 AM.

Details

Summary

Issue was found during compilation of V8 code inside android project with clang-3.9.
The folowing messages was shown:

/tmp/preprocessor-v8-msa-repro-f130c4.s: Assembler messages:
/tmp/preprocessor-v8-msa-repro-f130c4.s:33112: Error: operand 2 out of range `st.d $w0,23($16)'
clang-3.9: error: assembler command failed with exit code 1 (use -v to see invocation)

This issue is also manifesting on the latest upstream clang. More information here.
This patch implements checks for unaligned and out of range offsets for ST.* and LD.* Mips MSA instructions.

Diff Detail

Repository
rL LLVM

Event Timeline

mamidzic updated this revision to Diff 54819.Apr 25 2016, 12:56 AM
mamidzic retitled this revision from to [mips] Clang generates unaligned offset for MSA instruction st.d.
mamidzic updated this object.
mamidzic added subscribers: llvm-commits, petarj.
mamidzic updated this object.Apr 25 2016, 1:01 AM
mamidzic edited edge metadata.
mamidzic updated this object.
dsanders requested changes to this revision.Apr 25 2016, 2:32 AM
dsanders edited edge metadata.
dsanders added inline comments.
lib/Target/Mips/MipsInstrInfo.td
1076–1081 ↗(On Diff #54819)

For consistency with an existing microMIPS ComplexPattern (addrimm4lsl2) and the mem_simm_lsl* operands could we spell this 'addrimm10lsl2'?

lib/Target/Mips/MipsSEISelDAGToDAG.cpp
483 ↗(On Diff #54819)

EliminateFI -> eliminateFrameIndex?

488–492 ↗(On Diff #54819)

We shouldn't modify offsets in this code, we should only accept valid ones. Modifying the offset breaks the address calculation. One example of this is the O32 calling convention which can legitimately produce offsets that are unsuitable for the offset field of ld.[bhwd] and st.[bhwd] instructions (the ABI's stack alignment is insufficient to be able to guarantee that a vector argument/result is fully aligned). These instructions can still be used so long as the offset is added to the base address in a separate instruction since the spec permits unaligned addresses.

This code needs to fall back on selectAddrDefault() whenever the offset is inappropriate for the instructions instead of modifying the offset. We also need to do the alignment check in selectAddrFrameIndexOffset() so that we can account for the increased range that the scaled offsets allow.

test/CodeGen/Mips/msa/i5_ld_st.ll
68 ↗(On Diff #54819)

As noted above, it's incorrect to use an offset other than 9. The expected code should be something like:

addiu $3, $2, 9
ld.h $4, 0($3)

Similarly for the ld.[hwd] and st.[hwd] cases.

This revision now requires changes to proceed.Apr 25 2016, 2:32 AM
mamidzic marked 2 inline comments as done.May 6 2016, 5:08 AM
mamidzic added inline comments.
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
483 ↗(On Diff #54819)

Well both exist. There is MipsRegisterInfo::eliminateFrameIndex and MipsSERegisterInfo::eliminateFI. eliminateFrameIndex only calls eliminateFI and then the offset is actually being calculated.

488–492 ↗(On Diff #54819)

I have done the fall back on selectAddrDefault() when the offset is wrong, but I'm not sure what did you mean with the last sentence. Could you elaborate a bit?

mamidzic updated this revision to Diff 56399.May 6 2016, 5:08 AM
mamidzic edited edge metadata.

Changed the names of operands from addrimm10al[2,4,8] to addrimm10lsl[1,2,3].
Removed the changing of offsets in selectIntAddrMSAAlign(). If the unaligned offset is detected, selectAddrDefault() is now called.
Changed tests so that they reflect the changes in the patch.

dsanders requested changes to this revision.May 9 2016, 3:23 AM
dsanders edited edge metadata.
dsanders added inline comments.
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
483 ↗(On Diff #56399)

I couldn't find it because I was searching for 'EliminateFI' from the comment instead of the 'eliminateFI' found in our backend. It's probably best to refer to eliminateFrameIndex since that's the interface with the target independent code but 'eliminateFI' is ok too as long as we correct the upper case 'E'

488–492 ↗(On Diff #56399)

Thanks.

I have done the fall back on selectAddrDefault() when the offset is wrong, but I'm not sure what did you mean with the last sentence. Could you elaborate a bit?

The current code checks for an offset that is a simm10 and is a multiple of the alignment but it should be checking for a simm10/simm11/simm12/simm13 (depending on the alignment) that is a multiple of the alignment. To put this another way, we need to check that the offset is a multiple of the alignment and that Offset / Alignment is a simm10.

For example, the offsets have to follow these constraints:

Instruction>=<=Multiple of
lw.b-102410231
lw.h-204820462
lw.w-409640924
lw.d-819281848

but the current implementation implements these rules:

Instruction>=<=Multiple of
lw.b-102410231
lw.h-102410222
lw.w-102410204
lw.d-102410168
This revision now requires changes to proceed.May 9 2016, 3:23 AM
mamidzic updated this revision to Diff 57137.May 13 2016, 1:31 AM
mamidzic updated this object.
mamidzic edited edge metadata.

Changed name of selectIntAddrMSA to selectIntAddrMSAAlign1, also relocated to be grouped with other MSAAlign functions.
Changed name of selectAddrRegImm10 to SelectAddrRegImmMSA because it's only used with st.* and ld.* instructions and it's not always Imm10. Also relocated it to be grouped with other MSA related functions.
Implemented checking of offset range for st.* and ld.* instructions.
Added valid and invalid offset range tests for st.* and ld.* instructions.
Fixed some indentation mistakes and typos.

mamidzic added inline comments.May 13 2016, 1:40 AM
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
488–492 ↗(On Diff #56399)

If I'm not mistaken, simm10 range is from -512 to 511 so I assumed you meant:

Instruction>=<=Multiple of
lw.b-5125111
lw.h-102410222
lw.w-204820444
lw.d-409640888
dsanders requested changes to this revision.May 16 2016, 6:37 AM
dsanders edited edge metadata.

I think we're nearly there. My main concern is the fragility of the alignment check if we do it where it currently is.

lib/Target/Mips/MipsISelDAGToDAG.h
79–92 ↗(On Diff #57137)

One last naming nit: We ought to switch out the mention of MSA for a mention of the immediate size and shift amount (e.g. selectAddrSimm10Lsl2) since these can be re-used for non-MSA purposes too. Removing the reference to 'MSA' should prevent people thinking it has MSA-specific special cases in the future.

lib/Target/Mips/MipsSEISelDAGToDAG.cpp
472–492 ↗(On Diff #57137)

If we have a shift amount rather than the alignment (like in the MC layer) then we can directly use something like '10 + ShiftAmount' rather than having to convert.

478–482 ↗(On Diff #57137)

Yes, you're right.

497–505 ↗(On Diff #57137)

I think we still need to sink the alignment check into selectAddrFrameIndexOffset() to make this check robust.

In the current code, if selectAddrRegImmMSA() returns 'Base' as something other than a FrameIndexSDNode such as (add ptr, 3) then the current code will accept invalid offsets again. Admittedly, the current implementation of selectAddrRegImmMSA() and the functions it calls can only match FrameIndexSDNode nodes right now but we should improve that as soon as possible.

This revision now requires changes to proceed.May 16 2016, 6:37 AM
mamidzic updated this revision to Diff 57606.May 18 2016, 6:16 AM
mamidzic edited edge metadata.

Removed selectIntAddrMSAAlign and selectAddrRegImmMSA
Changed name of following functions:

selectIntAddrMSAAlign1->selectIntAddrSImm10
selectIntAddrMSAAlign2->selectIntAddrSImm10Lsl1
selectIntAddrMSAAlign4->selectIntAddrSImm10Lsl2
selectIntAddrMSAAlign8->selectIntAddrSImm10Lsl3

Added ShiftAmount parameter to the selectAddrFrameIndexOffset.
Alignment check is now done in selectAddrFrameIndexOffset.

Hi, are there any news regarding this patch?

dsanders accepted this revision.Jul 28 2016, 8:05 AM
dsanders edited edge metadata.

LGTM with a nit

lib/Target/Mips/MipsSEISelDAGToDAG.cpp
311 ↗(On Diff #57606)

Please add a '!= 0' to make the intent of the check more obvious

This revision is now accepted and ready to land.Jul 28 2016, 8:05 AM
This revision was automatically updated to reflect the committed changes.