There are a few places where the alignment argument for AlignedAllocLike functions was previously hardcoded. This goes along with removing hardcoded arguments for the allocation size. It also allows alligned operator new to be given an alignment value in InstCombinerImpl::annotateAnyAllocSite and makes Heap To Stack add the proper alignment for aligned new. I'm sure this isn't the best way to do this but I am new to the LLVM codebase so I appreciate any suggestions on how to improve.
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
The AllocationFnData table was not properly formatted before my modifications. When running clang-format, it changed the formatting of the entire table. I formatted it back to how it looked before but fixed a few issues with it. I think this looks better and is easier to read but I am happy to set it back to the way clang-format likes it if that is desired. Let me know. I think that was the only issue with the build.
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | ||
---|---|---|
2594 | Works fine currently but we should replace Call.getOperand(1) with some more general API like getAllocSizeArg or so. |
llvm/include/llvm/Analysis/MemoryBuiltins.h | ||
---|---|---|
75 | Move this down to the new property section please. | |
76 | I'd suggest changing the return value from the operand index to the Value * of the operand or nullptr. This seems like it would cleanup the current client code a bit, and would also allow us to return constant exprs for any allocation function whose alignment is a (known) function of the constant allocated size. I'm not suggesting you do the last bit, just that you leave the potential open. | |
llvm/lib/Transforms/IPO/AttributorAttributes.cpp | ||
5957 | I think this block would be cleaner as: Value *Align = getAlignment(*AI.CB) .. } This lets you drop all the passing around indices. | |
6268–6270 | Same. |
Thanks for the suggestions! I had a feeling that there would be a better way than passing indexes around. I think I've mostly implemented them correctly. I'm not entirely sure if my use of getInitialValueOfAllocation is correct. I am also not sure about the part where getAllocSize has the possibility of creating a multiplication. Maybe that should return a pair of Values and let the caller create a multiplication if it wants?
Please move the getAllocSize parts to it's own patch. We were converging on an LGTM for the alignment bits, and I want to keep the discussion focused on that.
I'd suggest leaving the Attributor change to it's own review. I'm not familiar enough to review it easily. Let's get the allocation accessor in, and then iterate.
llvm/lib/Analysis/MemoryBuiltins.cpp | ||
---|---|---|
278 | Er, this does not work. You need to check that AlignmentParam is not -1, or this will crash. |
I've rolled back the addition of the size function and the changes to attributor that go with it (I'll put those together in a separate patch once this one is done). I've kept the changes to attributor that are related to alignment but I can remove those as well if you would like, I wasn't entirely sure if you meant for me to do that or not. Thanks!
llvm/lib/Analysis/MemoryBuiltins.cpp | ||
---|---|---|
278 | Good point, for some reason I assumed getOperand would return null for that case. Do I also need to check if it's too large? |
LGTM for everything outside of Attributor - those lines I'm unsure of whether there's a missing precondition on the argument being constant.
Do you have commit access? If not, I can land the LGTMed parts for you.
I am assuming that I don't have commit access since this is my first contribution so I would appreciate you landing the changes outside of Attributor.
I agree that someone experienced with Attributor should look at it to be sure. Looking at it again, I think that it probably does assume that it is constant and while I could put in a check, I'm not sure if there is a way to back out if it was not (maybe this was an issue even with the original aligned_alloc?). getAssumedConstant will return nullptr if it is sure that the value is not constant. getAPInt will return none if the result from getAssumedConstant is neither a known constant nor none (unsure if constant or not). The like after the line I changed then asserts that the result from getAPInt has a value.
Will do tomorrow morning.
So we're clear on the legal stuff, can you confirm that this is intended as a contribution to the LLVM project and that you agree to the license terms thereof?
I confirm that this is intended as a contribution to the LLVM project and that I agree to the license terms thereof.
Landed. When I went to land it, I noticed a couple of small issues, so this ended up being a small mini series rather than one patch.
commit 7febd60a90960ff1c74027c05394e134dad655a1 (HEAD -> main, origin/main)
Author: Bryce Wilson <bryce@brycemw.ca>
Date: Mon Jan 10 09:08:55 2022 -0800
[instcombine] Add align return attributes for operator new(..., align_val)
commit fb936595faa44ad9c8d8550b05ea95e7be5f4703
Author: Bryce Wilson <bryce@brycemw.ca>
Date: Mon Jan 10 08:58:44 2022 -0800
[MemoryBuiltins] Add field for alignment argument [NFC]
commit 332642e693509947d33ec5dbcbdc3fcf149f4a87
Author: Philip Reames <listmail@philipreames.com>
Date: Mon Jan 10 08:38:40 2022 -0800
Add test coverage for D116851
commit f4c54683d684100fffd307ddf773078429b83442
Author: Philip Reames <listmail@philipreames.com>
Date: Mon Jan 10 08:25:20 2022 -0800
[instcombine] Infer alignment for aligned_alloc with potentially zero size
BTW, https://clang.llvm.org/docs/AttributeReference.html#id330 ... is it broken just for me or.. ?
void *b(void *v, int align) __attribute__((alloc_size(2), alloc_align(2))) ; void *b(void *v, int align) { return v; }
; ModuleID = '/app/example.cpp' source_filename = "/app/example.cpp" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" ; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn allocsize(1) define dso_local i8* @_Z1bPvi(i8* readnone returned %0, i32 %1) local_unnamed_addr #0 { ret i8* %0 } attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn allocsize(1) "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } !llvm.module.flags = !{!0, !1} !llvm.ident = !{!2} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 7, !"uwtable", i32 1} !2 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git d23fa4f2f1319039b7d939a4bf68c493ba26b07a)"}
Clang seems to ignore alloc_align attribute?
If by "broken", you mean "unimplemented" yes. LLVM has no allocalign attribute.
(For the record, that's related, but not directly relevant to this patch. Your comment made it seem like there might be a regression here. I believe that not to be the case, do you agree?)
Yes, not related to this patch, I was just curious about that (if you know something more about that, etc..). Thanks.
There probably should be an allocalign attribute in the future once allocation functions are less hardcoded
llvm/lib/Analysis/MemoryBuiltins.cpp | ||
---|---|---|
64 | Thinking about this again.. Maybe this should go to Clang? We should really use allocsize attribute and annotate LibFuncs instead of using this hardcoded list. |
Move this down to the new property section please.