This is an archive of the discontinued LLVM Phabricator instance.

[CodeGen] Fix assertion failure on large types store
Needs ReviewPublic

Authored by kovdan01 on Apr 20 2022, 3:59 AM.

Details

Summary

The following IR:

%struct.large = type { [2500000 x i8] }

define void @foo(%struct.large %s, %struct.large* %p) {
  store %struct.large %s, %struct.large* %p, align 1
  ret void
}

caused assertion 'NumBits <= MAX_INT_BITS && "bitwidth too large"' failure.

The IR above is a minimized version from IR from an actual bug report. Keeping
in mind that such IR is discouraged, the compiler should not fail on a formally
valid input. The patch fixes this issue.

Fixing that also requires widening NumValues and NumOperands fields of SDNode
to avoid fail of another assertion about insufficient bit width of those fields.
Reordering of SDNode fields was done to keep sizeof(SDNode) == 80 on x86_64
Linux builds.

Diff Detail

Event Timeline

kovdan01 created this revision.Apr 20 2022, 3:59 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 20 2022, 3:59 AM
kovdan01 requested review of this revision.Apr 20 2022, 3:59 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 20 2022, 3:59 AM
kovdan01 added a comment.EditedApr 20 2022, 4:00 AM

UPD: fixed the problem, keep the comment for history.

As for now, the patch contains no tests. The reason is that a minimal test lasts unacceptably long (didn't manage to wait until end) with assertions enabled - the bottleneck is checkForCyclesHelper function. With expensive checks enabled, one more bottleneck appears: DAGTypeLegalizer::PerformExpensiveChecks. When commenting those functions bodies, minimal test with release-checked compiler lasts for about 160s on my PC. Could anyone suggest a way to test this patch correctly? IMHO looks like we can leave it without special test because the fix is pretty trivial, while I personally see no obvious way to test it.--

kovdan01 edited the summary of this revision. (Show Details)Apr 22 2022, 3:49 PM
kovdan01 added a reviewer: spatel.

Would be glad if someone could review this. Thanks!

RKSimon added inline comments.Apr 23 2022, 3:50 AM
llvm/lib/CodeGen/CodeGenPrepare.cpp
7463

Isn't this hard-coded to unsigned/uint32_t? What about exposing a typedef in SDNode instead so we can use std::numeric_limits? .

craig.topper added inline comments.Apr 23 2022, 1:25 PM
llvm/lib/CodeGen/CodeGenPrepare.cpp
7463

MAX_INT_BITS is 1<<23. It's related to there being 24 bits of subclass data available in llvm::Type

As for now, the patch contains no tests. The reason is that a minimal test lasts unacceptably long (didn't manage to wait until end) with assertions enabled - the bottleneck is checkForCyclesHelper function. With expensive checks enabled, one more bottleneck appears: DAGTypeLegalizer::PerformExpensiveChecks. When commenting those functions bodies, minimal test with release-checked compiler lasts for about 160s on my PC. Could anyone suggest a way to test this patch correctly? IMHO looks like we can leave it without special test because the fix is pretty trivial, while I personally see no obvious way to test it.

Since this in CodeGenPrepare, couldn't you write a test that uses opt -codegenprepare and not go through SelectionDAG?

kovdan01 updated this revision to Diff 424805.Apr 24 2022, 6:41 PM
kovdan01 edited the summary of this revision. (Show Details)

As for now, the patch contains no tests. The reason is that a minimal test lasts unacceptably long (didn't manage to wait until end) with assertions enabled - the bottleneck is checkForCyclesHelper function. With expensive checks enabled, one more bottleneck appears: DAGTypeLegalizer::PerformExpensiveChecks. When commenting those functions bodies, minimal test with release-checked compiler lasts for about 160s on my PC. Could anyone suggest a way to test this patch correctly? IMHO looks like we can leave it without special test because the fix is pretty trivial, while I personally see no obvious way to test it.

Since this in CodeGenPrepare, couldn't you write a test that uses opt -codegenprepare and not go through SelectionDAG?

Thanks for useful advice! That works, added llvm/test/CodeGen/Generic/codegen_prepare_large_structs.ll.

craig.topper added inline comments.Apr 25 2022, 9:00 AM
llvm/test/CodeGen/Generic/codegen_prepare_large_structs.ll
1 ↗(On Diff #424805)

I don't think tests in the Generic directory can use a triple. It requires the target to be built, but a target can be disabled by passing LLVM_TARGETS_TO_BUILD to cmake.

kovdan01 updated this revision to Diff 424938.Apr 25 2022, 9:27 AM
kovdan01 added inline comments.
llvm/test/CodeGen/Generic/codegen_prepare_large_structs.ll
1 ↗(On Diff #424805)

Makes sense, fixed, thanks!

Please split the CodeGenPrepare and SelectionDAG changes into separate patches.