Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CallPromotionUtils: Correctly use IndexSize when determining the bit width of pointer offsets. #119138

Merged
merged 1 commit into from
Dec 10, 2024

Conversation

resistor
Copy link
Collaborator

@resistor resistor commented Dec 8, 2024

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Owen Anderson (resistor)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/119138.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/CallPromotionUtils.cpp (+7-3)
  • (added) llvm/test/Transforms/Inline/promote-call-bitwidth.ll (+47)
diff --git a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp
index 17cba2e642a19a..5c8246c14b3882 100644
--- a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp
+++ b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp
@@ -692,14 +692,17 @@ bool llvm::tryPromoteCall(CallBase &CB) {
   if (!VTableEntryLoad)
     return false; // Not a vtable entry load.
   Value *VTableEntryPtr = VTableEntryLoad->getPointerOperand();
-  APInt VTableOffset(DL.getTypeSizeInBits(VTableEntryPtr->getType()), 0);
+  APInt VTableOffset(DL.getIndexSizeInBits(
+                         VTableEntryPtr->getType()->getPointerAddressSpace()),
+                     0);
   Value *VTableBasePtr = VTableEntryPtr->stripAndAccumulateConstantOffsets(
       DL, VTableOffset, /* AllowNonInbounds */ true);
   LoadInst *VTablePtrLoad = dyn_cast<LoadInst>(VTableBasePtr);
   if (!VTablePtrLoad)
     return false; // Not a vtable load.
   Value *Object = VTablePtrLoad->getPointerOperand();
-  APInt ObjectOffset(DL.getTypeSizeInBits(Object->getType()), 0);
+  APInt ObjectOffset(
+      DL.getIndexSizeInBits(Object->getType()->getPointerAddressSpace()), 0);
   Value *ObjectBase = Object->stripAndAccumulateConstantOffsets(
       DL, ObjectOffset, /* AllowNonInbounds */ true);
   if (!(isa<AllocaInst>(ObjectBase) && ObjectOffset == 0))
@@ -712,7 +715,8 @@ bool llvm::tryPromoteCall(CallBase &CB) {
       VTablePtrLoad, VTablePtrLoad->getParent(), BBI, 0, nullptr, nullptr);
   if (!VTablePtr)
     return false; // No vtable found.
-  APInt VTableOffsetGVBase(DL.getTypeSizeInBits(VTablePtr->getType()), 0);
+  APInt VTableOffsetGVBase(
+      DL.getIndexSizeInBits(VTablePtr->getType()->getPointerAddressSpace()), 0);
   Value *VTableGVBase = VTablePtr->stripAndAccumulateConstantOffsets(
       DL, VTableOffsetGVBase, /* AllowNonInbounds */ true);
   GlobalVariable *GV = dyn_cast<GlobalVariable>(VTableGVBase);
diff --git a/llvm/test/Transforms/Inline/promote-call-bitwidth.ll b/llvm/test/Transforms/Inline/promote-call-bitwidth.ll
new file mode 100644
index 00000000000000..f0e9f7aec00d6b
--- /dev/null
+++ b/llvm/test/Transforms/Inline/promote-call-bitwidth.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
+; RUN: opt -S -passes=inline < %s | FileCheck %s
+target datalayout = "e-m:e-p200:128:128:128:64-p:64:64-i64:64-i128:128-n64-S128-A200-P200-G200"
+target triple = "riscv64-unknown-freebsd13.0"
+
+define void @test(ptr addrspace(200) %arg1, ptr addrspace(200) %arg2) local_unnamed_addr addrspace(200) {
+; CHECK-LABEL: define {{[^@]+}}@test
+; CHECK-SAME: (ptr addrspace(200) [[ARG1:%.*]], ptr addrspace(200) [[ARG2:%.*]]) local_unnamed_addr addrspace(200) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load ptr addrspace(200), ptr addrspace(200) [[ARG2]], align 16
+; CHECK-NEXT:    call addrspace(200) void [[TMP0]](ptr addrspace(200) [[ARG1]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void @call_fnptr(ptr addrspace(200) %arg1, ptr addrspace(200) %arg2)
+  ret void
+}
+
+define internal void @call_fnptr(ptr addrspace(200) %this, ptr addrspace(200) %arg) unnamed_addr addrspace(200) align 2 {
+entry:
+  %0 = load ptr addrspace(200), ptr addrspace(200) %arg, align 16
+  call void %0(ptr addrspace(200) %this)
+  ret void
+}
+
+define void @test2(ptr addrspace(200) %this) local_unnamed_addr addrspace(200) {
+; CHECK-LABEL: define {{[^@]+}}@test2
+; CHECK-SAME: (ptr addrspace(200) [[THIS:%.*]]) local_unnamed_addr addrspace(200) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[VTABLE_I:%.*]] = load ptr addrspace(200), ptr addrspace(200) [[THIS]], align 16
+; CHECK-NEXT:    [[FN_I:%.*]] = load ptr addrspace(200), ptr addrspace(200) [[VTABLE_I]], align 16
+; CHECK-NEXT:    call addrspace(200) void [[FN_I]](ptr addrspace(200) [[THIS]])
+; CHECK-NEXT:    ret void
+;
+entry:
+  call void @call_via_vtable(ptr addrspace(200) %this)
+  ret void
+}
+
+define internal void @call_via_vtable(ptr addrspace(200) %this) unnamed_addr addrspace(200) {
+entry:
+  %0 = bitcast ptr addrspace(200) %this to ptr addrspace(200)
+  %vtable = load ptr addrspace(200), ptr addrspace(200) %0, align 16
+  %fn = load ptr addrspace(200), ptr addrspace(200) %vtable, align 16
+  call void %fn(ptr addrspace(200) %this)
+  ret void
+}

@resistor
Copy link
Collaborator Author

resistor commented Dec 9, 2024

Tagging @jrtc27 and @arichardson as this is a CHERI-derived change

Copy link
Member

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is my downstream commit CTSRD-CHERI/llvm-project@fb9fa37, would be nice if you could add Co-authored-by:.

Thanks for working on upstreaming these changes!

Copy link
Member

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with suggested changes.

@resistor
Copy link
Collaborator Author

Looks like this is my downstream commit CTSRD-CHERI/llvm-project@fb9fa37, would be nice if you could add Co-authored-by:.

Sure. Is that just written into the commit message, or do I need to do something special to make git recognize it?

@arichardson
Copy link
Member

Looks like this is my downstream commit CTSRD-CHERI/llvm-project@fb9fa37, would be nice if you could add Co-authored-by:.

Sure. Is that just written into the commit message, or do I need to do something special to make git recognize it?

Just needs to be a separate line in the commit message for github to recognize it. I believe I was still at Cambridge Uni back then so adding
Co-authored-by: Alexander Richardson <[email protected]> would be correct.

@resistor
Copy link
Collaborator Author

Looks like this is my downstream commit CTSRD-CHERI/llvm-project@fb9fa37, would be nice if you could add Co-authored-by:.

Sure. Is that just written into the commit message, or do I need to do something special to make git recognize it?

Just needs to be a separate line in the commit message for github to recognize it. I believe I was still at Cambridge Uni back then so adding Co-authored-by: Alexander Richardson <[email protected]> would be correct.

Done

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

…width of pointer offsets.

Co-authored-by: Alexander Richardson <[email protected]>
@resistor resistor merged commit 4027e2f into llvm:main Dec 10, 2024
8 checks passed
resistor added a commit that referenced this pull request Dec 11, 2024
…the bit width of pointer offsets. (#119138)"

Reverting due to ASAN bootstrap failures.

This reverts commit 4027e2f.
@resistor
Copy link
Collaborator Author

I just reverted this due to ASAN bootstrap failures. https://lab.llvm.org/buildbot/#/builders/52/builds/4390
I am investigating these failures ASAP.

@@ -712,7 +712,7 @@ bool llvm::tryPromoteCall(CallBase &CB) {
VTablePtrLoad, VTablePtrLoad->getParent(), BBI, 0, nullptr, nullptr);
if (!VTablePtr)
return false; // No vtable found.
APInt VTableOffsetGVBase(DL.getTypeSizeInBits(VTablePtr->getType()), 0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably FindAvailableLoadedValue can return a pointer-sized integer (really, anything that CastInst::isBitOrNoopPointerCastable) if you end up storing a uintptr_t that you then load and call. If so, stripAndAccumulateConstantOffsets returns its input for non-pointers and then the dyn_cast will definitely give null.

(Obviously not true on CHERI for various reasons)

The other instances are fine because they're using the pointer operands of loads so by definition are pointers, whereas this one is some random other Value that is known to be the same bit pattern as the value loaded here.

So probably line 713 needs to gain a type check. Maybe you could cast back instead, though I'd worry about provenance due to peeking through inttoptr(ptrtoint(...)), and AFAICT the former would make the new code behave like the old code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I'm doing a bootstrap build now to try to extract a test case. I'll put up a new PR with the test and the fix once I have that.

resistor added a commit to resistor/llvm-project that referenced this pull request Dec 11, 2024
…width of pointer offsets.

This reapplies llvm#119138 with a defensive fix for the assertion failure when building libcxx.
Unfortunately the failure does not reproduce on my machine, so I am not able to extract a test case.

The key insight for the fix comes from jrtc, who observes that `VTablePtr` may, in fact,
not be a pointer on return from `FindAvailableLoadedValue`. This is easily worked around,
because we are guaranteed that the vtable being manipulated is the same one accessed via
`VTablePtrLoad` earlier, and thus can obtain the address space from there.

Co-authored-by: Alexander Richardson <[email protected]>
resistor added a commit to resistor/llvm-project that referenced this pull request Dec 11, 2024
…width of pointer offsets.

This reapplies llvm#119138 with a defensive fix for the assertion failure when building libcxx.
Unfortunately the failure does not reproduce on my machine, so I am not able to extract a test case.

The key insight for the fix comes from jrtc, who observes that `VTablePtr` may, in fact,
not be a pointer on return from `FindAvailableLoadedValue`. This is easily worked around,
because we are guaranteed that the vtable being manipulated is the same one accessed via
`VTablePtrLoad` earlier, and thus can obtain the address space from there.

Co-authored-by: Alexander Richardson <[email protected]>
resistor added a commit to resistor/llvm-project that referenced this pull request Dec 11, 2024
…width of pointer offsets.

This reapplies llvm#119138 with a defensive fix for the assertion failure when building libcxx.
Unfortunately the failure does not reproduce on my machine, so I am not able to extract a test case.

The key insight for the fix comes from Jessica Clarke, who observes that `VTablePtr` may, in fact,
not be a pointer on return from `FindAvailableLoadedValue`.

Co-authored-by: Alexander Richardson <[email protected]>
resistor added a commit that referenced this pull request Dec 11, 2024
…width of pointer offsets. (#119483)

This reapplies #119138 with a defensive fix for the assertion failure
when building libcxx.
Unfortunately the failure does not reproduce on my machine, so I am not
able to extract a test case.

The key insight for the fix comes from Jessica Clarke, who observes that
`VTablePtr` may, in fact,
not be a pointer on return from `FindAvailableLoadedValue`.

Co-authored-by: Alexander Richardson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants