Open Quuxplusone opened 4 years ago
Bugzilla Link | PR47395 |
Status | CONFIRMED |
Importance | P enhancement |
Reported by | Scott Waye (scott.waye@hubse.com) |
Reported on | 2020-09-02 06:43:59 -0700 |
Last modified on | 2020-09-03 05:37:21 -0700 |
Version | trunk |
Hardware | PC Windows NT |
CC | dblaikie@gmail.com, efriedma@quicinc.com, llvm-bugs@lists.llvm.org, tlively@google.com, yuanfang.chen@sony.com |
Fixed by commit(s) | |
Attachments | |
Blocks | |
Blocked by | |
See also |
Thanks for the report! Yes, I was able to reproduce this problem. It would be great if someone more familiar with this part of the code could take a look, though :)
If it's taking hours to read a 240MB bitcode file, there must be some non-linear algorithm involved. Looking at BitcodeReaderValueList::resolveConstantForwardRefs , I can only come up with one potential source of non-linearity: calling replaceAllUsesWith() on every element of a large array could be O(N^2). (It looks like the original author realized this was a possibility, which is why it doesn't RAUW the placeholder itself. But the reasoning was applied incompletely.)
Does the testcase have an array with a lot of constant expression operands somewhere?
It's possible we could also change the way we write bitcode files to avoid forward references more aggressively; not sure how the ordering works off the top of my head.
Yes, there are quite a few e.g.
@__FrozenSegmentRegionStart = global [278553 x i32*] [i32* null, i32* bitcast
([18 x i32*]* @__EEType_String to i32*), i32* null, i32* null, i32* null
There's some even bigger ones, but vim is having a hard time with the length of
the lines, but there's at least one with 1.7 million combinations of
bitcast(i8* getelementptr....
(In reply to Scott Waye from comment #3)
> There's some even bigger ones, but vim is having a hard time with the length
> of the lines
The POSIX fold command should be able to handle arbitrarily long lines.
How are you dumping the IR, though? If you're using llvm-dis, how long did it
take?
I'm using libLLVM at the point of finishing the compilation (of c# => LLVM IR)
with
#if DEBUG
Module.PrintToFile(Path.ChangeExtension(_objectFilePath, ".txt"));
#endif //DEBUG
The PrintToFile dumps the textual representation and it completes in a normal
amount of time given that its 1.5GB.
This method goes to
[DllImport(LibraryPath, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LLVMPrintModuleToFile", ExactSpelling = true)]
[return: NativeTypeName("LLVMBool")]
public static extern int PrintModuleToFile([NativeTypeName("LLVMModuleRef")] LLVMOpaqueModule* M, [NativeTypeName("const char *")] sbyte* Filename, [NativeTypeName("char **")] sbyte** ErrorMessage);
i.e. LLVMPrintModuleToFile in libLLVM
by "normal" I've not actually measured it, but I think its around 30 seconds.
here's the first few lines of that large array
@__embedded_metadata = global [1713228 x i32*] [i32* bitcast (i8* getelementptr
(i8, i8* null, i32 -559030275) to i32*), i32* bitcast (i8* getelementptr (i8, i8
* null, i32 1493321100) to i32*), i32* bitcast (i8* getelementptr (i8, i8* null,
i32 621213955) to i32*), i32* bitcast (i8* getelementptr (i8, i8* null, i32 -92
1973496) to i32*), i32* bitcast (i8* getelementptr (i8, i8* null, i32 420509964)
to i32*), i32* bitcast (i8* getelementptr (i8, i8* null, i32 1360507156) to i32
*), i32* bitcast (i8* getelementptr (i8, i8* null, i32 -920712933) to i32*), i32
* bitcast (i8* getelementptr (i8, i8* null, i32 1227260194) to i32*), i32* bitca
st (i8* getelementptr (i8, i8* null, i32 -1121234646) to i32*), i32* bitcast (i8
while I've got you, this array is basically just packing numbers. If there's a more efficient way to do that, over a bunch of geps, I'm all ears.
Probably you should be using inttoptr instead of gep on a null pointer.
I have a patch I think should fix this; will post soon.
Thanks! I can confirm that with this patch the compile time is back to 3 minutes.