It appears to be better IR-wise to aggressively scalarize it,
rather than relying on gathering it, and leaving it as-is.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/test/Transforms/Scalarizer/basic.ll | ||
---|---|---|
611 ↗ | (On Diff #275249) | Previously we'd end up with https://godbolt.org/z/HDKdqh %val0 = load <4 x i32>, <4 x i32>* %src, align 16 %val0.i0 = extractelement <4 x i32> %val0, i32 0 %val1.i0 = shl i32 1, %val0.i0 %val0.i1 = extractelement <4 x i32> %val0, i32 1 %val1.i1 = shl i32 2, %val0.i1 %val0.i2 = extractelement <4 x i32> %val0, i32 2 %val1.i2 = shl i32 3, %val0.i2 %val0.i3 = extractelement <4 x i32> %val0, i32 3 %val1.i3 = shl i32 4, %val0.i3 %val1.upto0 = insertelement <4 x i32> undef, i32 %val1.i0, i32 0 %val1.upto1 = insertelement <4 x i32> %val1.upto0, i32 %val1.i1, i32 1 %val1.upto2 = insertelement <4 x i32> %val1.upto1, i32 %val1.i2, i32 2 %val1 = insertelement <4 x i32> %val1.upto2, i32 %val1.i3, i32 3 %val2 = extractelement <4 x i32> %val1, i32 3 ret i32 %val2 |
@lebedev.ri this is causing assertion failures and verification failures in some of our downstream tests. Here's a test case:
$ cat reduced.ll define void @main(<3 x i32> inreg %w) { entry: %a = extractelement <3 x i32> undef, i32 0 %b = extractelement <3 x i32> undef, i32 1 %x = extractelement <3 x i32> %w, i32 2 %y = insertelement <4 x i32> undef, i32 %x, i32 2 %z = insertelement <4 x i32> %y, i32 undef, i32 3 store <4 x i32> %z, <4 x i32> addrspace(7)* undef, align 16 ret void } $ ~/llvm-debug/bin/opt -scalarizer -o /dev/null reduced.ll Instruction does not dominate all uses! <badref> = extractelement [145938144 x half] <badref>, i32 undef %z.upto2 = insertelement <4 x i32> undef, i32 <badref>, i32 2 in function main LLVM ERROR: Broken function found, compilation aborted!
Thank you for a great reproducer! Fixed in rGdb05f2e34a5e9380ddcc199d6687531108d795e4.
I unfortunately still see some problems (related to the Scalarizer changes, and probably this patch):
> cat scalarizer-bug.ll ; RUN: opt < %s -scalarizer -S -o - define void @foo() { vector.ph: br label %vector.body115 vector.body115: ; preds = %vector.body115, %vector.ph %vector.recur = phi <4 x i16> [ undef, %vector.ph ], [ %wide.load125, %vector.body115 ] %wide.load125 = load <4 x i16>, <4 x i16>* undef, align 1 br i1 undef, label %middle.block113, label %vector.body115 middle.block113: ; preds = %vector.body115 ret void } ----------------------------------------------------- > ~/opt.master -scalarizer scalarizer-bug.ll -S opt.master: ../lib/IR/Value.cpp:458: void llvm::Value::doRAUW(llvm::Value *, llvm::Value::ReplaceMetadataUses): Assertion `!contains(New, this) && "this->replaceAllUsesWith(expr(this)) is NOT valid!"' failed. PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace. Stack dump: 0. Program arguments: /home/uabbpet/opt.master -scalarizer scalarizer-bug.ll -S 1. Running pass 'Function Pass Manager' on module 'scalarizer-bug.ll'. 2. Running pass 'Scalarize vector operations' on function '@foo' Abort
Hm, this is saddening. I've fixed it in rG16266e63963ad6ee27ad21983a9366ab313dfd03, but are there more?
Ah, maybe I was so occupied reducing the fault so I missed that there was another fix. I actually did take a look in github just to avoid reporting a problem that had been fixed, but must have done it just before rG16266e63963ad6ee27ad21983a9366ab313dfd03 landed.
I'll fetch, rebuild, and test. Let you know if it didn't help.
Nono, rG16266e63963ad6ee27ad21983a9366ab313dfd03 is the fix as a reaction to the bug you reported, your report wasn't a duplicate, sorry for confusion.
I'll fetch, rebuild, and test. Let you know if it didn't help.
Yes, please, thank you!
Ah, thanks! (That was such a quick fix/response so I thought someone else had discovered the same problem.)
I'll fetch, rebuild, and test. Let you know if it didn't help.
Yes, please, thank you!
The fix works fine. So I don't know about more problems right now.
We have seen some issues with missing symbols during linking that I think are caused by this patch. The origin of this is downstream fuzz testing.
The global variable aglobal is renamed:
$ cat global.ll @aglobal = dso_local global i16 0, align 1 @b = dso_local local_unnamed_addr global i16 0, align 1 define dso_local void @c() local_unnamed_addr { entry: %d.sroa.0.1.vec.extract = extractelement <4 x i16*> <i16* @aglobal, i16* @aglobal, i16* @aglobal, i16* @aglobal>, i32 1 %0 = ptrtoint i16* %d.sroa.0.1.vec.extract to i16 store i16 %0, i16* @b, align 1 ret void } $ opt -scalarizer global.ll -S ; ModuleID = 'global.ll' source_filename = "global.ll" @d.sroa.0.1.vec.extract = dso_local global i16 0, align 1 @b = dso_local local_unnamed_addr global i16 0, align 1 define dso_local void @c() local_unnamed_addr { entry: %0 = ptrtoint i16* @d.sroa.0.1.vec.extract to i16 store i16 %0, i16* @b, align 1 ret void }
I see that the global is renamed, https://godbolt.org/z/PM95se, it's not really intentional.
But i think something else is missing in this test - what's the failure? -verify passes
I don't think there is a verifier that points out this issue. But consider if there is another .ll file which has an external reference to the global:
@aglobal = external dso_local local_unnamed_addr global i16, align 1 define dso_local i16 @main() local_unnamed_addr #0 { entry: %0 = load i16, i16* @aglobal, align 1 ret i16 %0 }
In this case you get link error when @aglobal has been renamed in global.ll.