This is an archive of the discontinued LLVM Phabricator instance.

[AMDGPU] Fix crash legalizing G_EXTRACT_VECTOR_ELT with negative index
ClosedPublic

Authored by foad on Aug 30 2022, 6:11 AM.

Diff Detail

Event Timeline

foad created this revision.Aug 30 2022, 6:11 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2022, 6:11 AM
foad requested review of this revision.Aug 30 2022, 6:11 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 30 2022, 6:11 AM
foad added reviewers: arsenm, Peter, Restricted Project.Aug 30 2022, 6:12 AM

IdxVal >= 0 check looks fine to me,
but what looks wrong in this test is that i1 1(true in llvm ir) index is translated to %7:_(s32) = G_CONSTANT i32 -1
IRTranslator::translateExtractElement did not expect i1 indices and since indices are (afaik) positive zext would make more sense then sext in:
APInt NewIdx = CI->getValue().sextOrTrunc(PreferredVecIdxWidth);
->
APInt NewIdx = CI->getValue().zextOrTrunc(PreferredVecIdxWidth);

Language ref does not specify required type for index, although we probably expected i32,
vector in test %I has two elements and i1 is enough to hold index, so globalisel should probably treat i1 true and false as 0 and 1 i32 indices .

foad added a comment.Aug 30 2022, 8:00 AM

Agreed, indexes should be unsigned, and this should be documented in the LangRef like it is for the shl instruction: ‘op2’ is treated as an unsigned value.

Peter added a comment.Aug 30 2022, 8:33 AM

Agree. This case seems unique to i1. Any other index with negative constant value would be ignored by translator.

llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
2392

You might want to add the non-negative test here too. However, I haven't been able to find a test case that crashed here yet.

I'll send an issue to github and tag this post.

foad updated this revision to Diff 457204.Sep 1 2022, 2:01 AM

Speculative fix for G_INSERT_VECTOR_ELT.

foad marked an inline comment as done.Sep 1 2022, 2:01 AM
arsenm added a comment.Sep 8 2022, 8:31 AM

I'd somewhat prefer a mir test for this in case some IR optimization decided to start deleting these earlier

IdxVal >= 0 check looks fine to me,
but what looks wrong in this test is that i1 1(true in llvm ir) index is translated to %7:_(s32) = G_CONSTANT i32 -1
IRTranslator::translateExtractElement did not expect i1 indices and since indices are (afaik) positive zext would make more sense then sext in:
APInt NewIdx = CI->getValue().sextOrTrunc(PreferredVecIdxWidth);
->
APInt NewIdx = CI->getValue().zextOrTrunc(PreferredVecIdxWidth);

Language ref does not specify required type for index, although we probably expected i32,
vector in test %I has two elements and i1 is enough to hold index, so globalisel should probably treat i1 true and false as 0 and 1 i32 indices .

The type conversion in the IRTranslator surprises me. I would expect to pass through the IR type and let the legalizer deal with it

llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
2346

Why not switch this to getZExtValue?

llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-extractelement-crash.ll
2 ↗(On Diff #457204)

-global-isel to the front

foad updated this revision to Diff 458996.Sep 9 2022, 2:36 AM

Switch to MIR test case.

foad marked an inline comment as done.Sep 9 2022, 2:37 AM
arsenm accepted this revision.Sep 9 2022, 7:03 AM
This revision is now accepted and ready to land.Sep 9 2022, 7:03 AM