Skip to content

[GlobalISel] Check width of APInts in Reassoc PtrAdd combine #84335

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

Closed
wants to merge 3 commits into from

Conversation

mbrkusanin
Copy link
Collaborator

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Mar 7, 2024

@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-amdgpu

Author: Mirko Brkušanin (mbrkusanin)

Changes

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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+2-1)
  • (added) llvm/test/CodeGen/AMDGPU/GlobalISel/combine-ptradd-reassociation.mir (+49)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 2f18a64ca285bd..d772f3d228d0de 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -4653,7 +4653,8 @@ bool CombinerHelper::matchReassocFoldConstantsInSubTree(GPtrAdd &MI,
     return false;
 
   MatchInfo = [=, &MI](MachineIRBuilder &B) {
-    auto NewCst = B.buildConstant(MRI.getType(Src2Reg), *C1 + *C2);
+    auto NewCst = B.buildConstant(MRI.getType(Src2Reg),
+                                  C1->sextOrTrunc(C2->getBitWidth()) + *C2);
     Observer.changingInstr(MI);
     MI.getOperand(1).setReg(LHSSrc1);
     MI.getOperand(2).setReg(NewCst.getReg(0));
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-ptradd-reassociation.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-ptradd-reassociation.mir
new file mode 100644
index 00000000000000..67c8548f9272a9
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-ptradd-reassociation.mir
@@ -0,0 +1,49 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=amdgcn -run-pass=amdgpu-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            test_different_sizes_64_32
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $sgpr0_sgpr1
+
+    ; CHECK-LABEL: name: test_different_sizes_64_32
+    ; CHECK: liveins: $sgpr0_sgpr1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $sgpr0_sgpr1
+    ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p1) = G_INTTOPTR [[COPY]](s64)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
+    ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p1) = G_PTR_ADD [[INTTOPTR]], [[C]](s32)
+    ; CHECK-NEXT: SI_RETURN implicit [[PTR_ADD]](p1)
+    %0:_(s64) = COPY $sgpr0_sgpr1
+    %1:_(s64) = G_CONSTANT i64 8
+    %2:_(s32) = G_CONSTANT i32 4
+    %3:_(p1) = G_INTTOPTR %0(s64)
+    %4:_(p1) = G_PTR_ADD %3, %1(s64)
+    %5:_(p1) = G_PTR_ADD %4, %2(s32)
+    SI_RETURN implicit %5(p1)
+...
+---
+name:            test_different_sizes_32_64
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $sgpr0_sgpr1
+
+    ; CHECK-LABEL: name: test_different_sizes_32_64
+    ; CHECK: liveins: $sgpr0_sgpr1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $sgpr0_sgpr1
+    ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p1) = G_INTTOPTR [[COPY]](s64)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
+    ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p1) = G_PTR_ADD [[INTTOPTR]], [[C]](s64)
+    ; CHECK-NEXT: SI_RETURN implicit [[PTR_ADD]](p1)
+    %0:_(s64) = COPY $sgpr0_sgpr1
+    %1:_(s64) = G_CONSTANT i64 8
+    %2:_(s32) = G_CONSTANT i32 4
+    %3:_(p1) = G_INTTOPTR %0(s64)
+    %4:_(p1) = G_PTR_ADD %3, %2(s32)
+    %5:_(p1) = G_PTR_ADD %4, %1(s64)
+    SI_RETURN implicit %5(p1)
+...

@@ -4653,7 +4653,8 @@ bool CombinerHelper::matchReassocFoldConstantsInSubTree(GPtrAdd &MI,
return false;

MatchInfo = [=, &MI](MachineIRBuilder &B) {
auto NewCst = B.buildConstant(MRI.getType(Src2Reg), *C1 + *C2);
auto NewCst = B.buildConstant(MRI.getType(Src2Reg),
C1->sextOrTrunc(C2->getBitWidth()) + *C2);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should we always pick larger one instead?

Copy link

Choose a reason for hiding this comment

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

unsigned BitWidth = std::max(C1->getBitWidth(), C2->getBitWidth());

see #82927

@jayfoad
Copy link
Contributor

jayfoad commented Mar 7, 2024

Allowing arbitrary widths for the RHS of G_PTR_ADD makes me very uncomfortable. I would much prefer enforcing that the RHS has the same bitwidth as the index size of the pointer's address space. See also #81473.

@jayfoad jayfoad requested a review from Pierre-vh March 7, 2024 16:49
@tschuett
Copy link

tschuett commented Mar 7, 2024

If you ask for getIConstantVRegValWithLookThrough from a s64 register, there is no guarantee that the bitwidth of APInt is 64 bit. If I have some fancy non integral AS with 128bit pointers, why should the offset of G_PTR_ADD be 128bit?

The test case is using the pre-legalizer combiner. I bet the real assert was in a bigger input.

@jayfoad
Copy link
Contributor

jayfoad commented Mar 7, 2024

If you ask for getIConstantVRegValWithLookThrough from a s64 register, there is no guarantee that the bitwidth of APInt is 64 bit.

Yes that should be guaranteed. If getIConstantVRegValWithLookThrough looks through a truncation or extension, it truncates or extends the APInt accordingly before returning it. Do you have an example where this does not work?

@jayfoad
Copy link
Contributor

jayfoad commented Mar 8, 2024

Allowing arbitrary widths for the RHS of G_PTR_ADD makes me very uncomfortable. I would much prefer enforcing that the RHS has the same bitwidth as the index size of the pointer's address space. See also #81473.

#84352

@mbrkusanin mbrkusanin force-pushed the fix-combine-reassoc-ptradd branch from 22faed6 to c87d504 Compare March 8, 2024 13:44
APInt NewConst = C1->sext(BitWidth) + C2->sext(BitWidth);
LLT Type =
MRI.getType(C1->getBitWidth() > C2->getBitWidth() ? LHSSrc2 : Src2Reg);
// Pick correct size for the constant based on the address space
Copy link
Contributor

Choose a reason for hiding this comment

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

If #84352 is accepted then this won't be necessary - you can rely on C1 and C2 both having the correct (same) width already.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok then

@mbrkusanin mbrkusanin closed this Mar 8, 2024
@mbrkusanin mbrkusanin deleted the fix-combine-reassoc-ptradd branch March 8, 2024 14:23
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.

4 participants