Skip to content

Commit 01801d5

Browse files
committed
[rs4gc] Fix a latent bug around attribute stripping for intrinsics
This change fixes a latent bug which was exposed by a change currently in review (https://reviews.llvm.org/D99802#2685032). The story on this is a bit involved. Without this change, what ended up happening with the pending review was that we'd strip attributes off intrinsics, and then selectiondag would fail to lower the intrinsic. Why? Because the lowering of the intrinsic relies on the presence of the readonly attribute. We don't have a matcher to select the case where there's a glue node needed. Now, on the surface, this still seems like a codegen bug. However, here it gets fun. I was unable to reproduce this with a standalone test at all, and was pretty much struck until skatkov provided the critical detail. This reproduces only when RS4GC and codegen are run in the same process and context. Why? Because it turns out we can't roundtrip the stripped attribute through serialized IR! We'll happily print out the missing attribute, but when we parse it back, the auto-upgrade logic has a side effect of blindly overwriting attributes on intrinsics with those specified in Intrinsics.td. This makes it impossible to exercise SelectionDAG from a standalone test case. At this point, I decided to treat this an RS4GC bug as a) we don't need to strip in this case, and b) I could write a test which shows the correct behavior to ensure this doesn't break again in the future. As an aside, I'd originally set out to handle libfuncs too - since in theory they might have the same issues - but backed away quickly when I realized how the semantics of builtin, nobuiltin, and no-builtin-x all interacted. I'm utterly convinced that no part of the optimizer handles that correctly, and decided not to open that can of worms here.
1 parent 9423f78 commit 01801d5

File tree

3 files changed

+23
-0
lines changed

3 files changed

+23
-0
lines changed

llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2594,6 +2594,16 @@ static void RemoveNonValidAttrAtIndex(LLVMContext &Ctx, AttrHolder &AH,
25942594
static void stripNonValidAttributesFromPrototype(Function &F) {
25952595
LLVMContext &Ctx = F.getContext();
25962596

2597+
// Intrinsics are very delicate. Lowering sometimes depends the presence
2598+
// of certain attributes for correctness, but we may have also inferred
2599+
// additional ones in the abstract machine model which need stripped. This
2600+
// assumes that the attributes defined in Intrinsic.td are conservatively
2601+
// correct for both physical and abstract model.
2602+
if (Intrinsic::ID id = F.getIntrinsicID()) {
2603+
F.setAttributes(Intrinsic::getAttributes(Ctx, id));
2604+
return;
2605+
}
2606+
25972607
for (Argument &A : F.args())
25982608
if (isa<PointerType>(A.getType()))
25992609
RemoveNonValidAttrAtIndex(Ctx, F,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; RUN: opt < %s -S -rewrite-statepoints-for-gc | FileCheck %s
2+
3+
; CHECK: Function Attrs: nounwind readnone
4+
; CHECK: declare i64 @llvm.x86.sse2.cvttsd2si64(<2 x double>)
5+
declare i64 @llvm.x86.sse2.cvttsd2si64(<2 x double>)
6+
7+
define i64 @test(<2 x double> %arg) {
8+
%ret = call i64 @llvm.x86.sse2.cvttsd2si64(<2 x double> %arg)
9+
ret i64 %ret
10+
}
11+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if not 'X86' in config.root.targets:
2+
config.unsupported = True

0 commit comments

Comments
 (0)