[llvm] [EarlyCSE] Rematerialize alignment assumption. (PR #109131)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 19 13:34:17 PDT 2024


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/109131

>From 3ddc96ff5b39785015e6cc9b405add95c5326baf Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 18 Sep 2024 13:38:52 +0100
Subject: [PATCH 1/2] [EarlyCSE] Rematerialize alignment assumption.

---
 llvm/lib/Transforms/Scalar/EarlyCSE.cpp             | 13 +++++++++++++
 .../EarlyCSE/materialize-align-assumptions.ll       |  3 +++
 2 files changed, 16 insertions(+)

diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index cf11f5bc885a75..743b333987bc9a 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -31,6 +31,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
@@ -1588,6 +1589,18 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
         if (InVal.IsLoad)
           if (auto *I = dyn_cast<Instruction>(Op))
             combineMetadataForCSE(I, &Inst, false);
+
+        // If the load has align metadata, preserve it via an alignment
+        // assumption. Note that this doesn't use salavageKnowledge, as we need
+        // to create the assumption for the value we replaced the load with.
+        if (auto *AlignMD = Inst.getMetadata(LLVMContext::MD_align)) {
+          auto *A = mdconst::extract<ConstantInt>(AlignMD->getOperand(0));
+          if (Op->getPointerAlignment(SQ.DL).value() % A->getZExtValue() != 0) {
+            IRBuilder B(&Inst);
+            B.CreateAlignmentAssumption(SQ.DL, Op, A);
+          }
+        }
+
         if (!Inst.use_empty())
           Inst.replaceAllUsesWith(Op);
         salvageKnowledge(&Inst, &AC);
diff --git a/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll b/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll
index ea63376957162b..628577b0975071 100644
--- a/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll
+++ b/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll
@@ -10,6 +10,7 @@ define ptr @align_replacement_does_not_have_align_metadata(ptr noalias %p) {
 ; CHECK-NEXT:    call void @foo(ptr [[L_1]])
 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[L_1]], i64 4
 ; CHECK-NEXT:    store ptr [[GEP]], ptr [[P]], align 8
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[GEP]], i64 4) ]
 ; CHECK-NEXT:    ret ptr [[GEP]]
 ;
   %l.1 = load ptr, ptr %p, align 8
@@ -27,6 +28,7 @@ define ptr @align_replacement_does_not_have_align_metadata2(ptr noalias %p) {
 ; CHECK-NEXT:    [[L_1:%.*]] = load ptr, ptr [[P]], align 8
 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[L_1]], i64 4
 ; CHECK-NEXT:    store ptr [[GEP]], ptr [[P]], align 8
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[GEP]], i64 4) ]
 ; CHECK-NEXT:    ret ptr [[GEP]]
 ;
   %l.1 = load ptr, ptr %p, align 8
@@ -54,6 +56,7 @@ define ptr @align_replacement_has_smaller_alignment(ptr noalias %p) {
 ; CHECK-SAME: ptr noalias [[P:%.*]]) {
 ; CHECK-NEXT:    [[L_1:%.*]] = load ptr, ptr [[P]], align 8, !align [[META0]]
 ; CHECK-NEXT:    call void @foo(ptr [[L_1]])
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[L_1]], i64 8) ]
 ; CHECK-NEXT:    ret ptr [[L_1]]
 ;
   %l.1 = load ptr, ptr %p, align 8, !align !0

>From 31a095ce99f14136f3943cdb74b91d74bbadee31 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 19 Sep 2024 21:33:40 +0100
Subject: [PATCH 2/2] !fixup check noundef

---
 llvm/lib/Transforms/Scalar/EarlyCSE.cpp       | 20 ++++++-----
 .../EarlyCSE/materialize-align-assumptions.ll | 35 ++++++++++++++-----
 2 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index 743b333987bc9a..8d2952ce758d4c 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -1590,14 +1590,18 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
           if (auto *I = dyn_cast<Instruction>(Op))
             combineMetadataForCSE(I, &Inst, false);
 
-        // If the load has align metadata, preserve it via an alignment
-        // assumption. Note that this doesn't use salavageKnowledge, as we need
-        // to create the assumption for the value we replaced the load with.
-        if (auto *AlignMD = Inst.getMetadata(LLVMContext::MD_align)) {
-          auto *A = mdconst::extract<ConstantInt>(AlignMD->getOperand(0));
-          if (Op->getPointerAlignment(SQ.DL).value() % A->getZExtValue() != 0) {
-            IRBuilder B(&Inst);
-            B.CreateAlignmentAssumption(SQ.DL, Op, A);
+        // If the load has align and noundef metadata, preserve it via an
+        // alignment assumption. Note that this doesn't use salavageKnowledge,
+        // as we need to create the assumption for the value we replaced the
+        // load with.
+        if (Inst.hasMetadata(LLVMContext::MD_noundef)) {
+          if (auto *AlignMD = Inst.getMetadata(LLVMContext::MD_align)) {
+            auto *A = mdconst::extract<ConstantInt>(AlignMD->getOperand(0));
+            if (Op->getPointerAlignment(SQ.DL).value() % A->getZExtValue() !=
+                0) {
+              IRBuilder B(&Inst);
+              B.CreateAlignmentAssumption(SQ.DL, Op, A);
+            }
           }
         }
 
diff --git a/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll b/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll
index 628577b0975071..837a73a00d6431 100644
--- a/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll
+++ b/llvm/test/Transforms/EarlyCSE/materialize-align-assumptions.ll
@@ -3,6 +3,24 @@
 
 declare void @foo(ptr)
 
+define ptr @align_replacement_does_not_have_align_metadata_missing_noundef(ptr noalias %p) {
+; CHECK-LABEL: define ptr @align_replacement_does_not_have_align_metadata_missing_noundef(
+; CHECK-SAME: ptr noalias [[P:%.*]]) {
+; CHECK-NEXT:    [[L_1:%.*]] = load ptr, ptr [[P]], align 8
+; CHECK-NEXT:    call void @foo(ptr [[L_1]])
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[L_1]], i64 4
+; CHECK-NEXT:    store ptr [[GEP]], ptr [[P]], align 8
+; CHECK-NEXT:    ret ptr [[GEP]]
+;
+  %l.1 = load ptr, ptr %p, align 8
+  call void @foo(ptr %l.1)
+  %l.2 = load ptr, ptr %p, align 8
+  %gep = getelementptr i8, ptr %l.2, i64 4
+  store ptr %gep, ptr %p, align 8
+  %l.3 = load ptr, ptr %p, align 8, !align !0
+  ret ptr %l.3
+}
+
 define ptr @align_replacement_does_not_have_align_metadata(ptr noalias %p) {
 ; CHECK-LABEL: define ptr @align_replacement_does_not_have_align_metadata(
 ; CHECK-SAME: ptr noalias [[P:%.*]]) {
@@ -18,7 +36,7 @@ define ptr @align_replacement_does_not_have_align_metadata(ptr noalias %p) {
   %l.2 = load ptr, ptr %p, align 8
   %gep = getelementptr i8, ptr %l.2, i64 4
   store ptr %gep, ptr %p, align 8
-  %l.3 = load ptr, ptr %p, align 8, !align !0
+  %l.3 = load ptr, ptr %p, align 8, !align !0, !noundef !{}
   ret ptr %l.3
 }
 
@@ -34,7 +52,7 @@ define ptr @align_replacement_does_not_have_align_metadata2(ptr noalias %p) {
   %l.1 = load ptr, ptr %p, align 8
   %gep = getelementptr i8, ptr %l.1, i64 4
   store ptr %gep, ptr %p, align 8
-  %l.2 = load ptr, ptr %p, align 8, !align !0
+  %l.2 = load ptr, ptr %p, align 8, !align !0, !noundef !{}
   ret ptr %l.2
 }
 
@@ -61,7 +79,7 @@ define ptr @align_replacement_has_smaller_alignment(ptr noalias %p) {
 ;
   %l.1 = load ptr, ptr %p, align 8, !align !0
   call void @foo(ptr %l.1)
-  %l.2 = load ptr, ptr %p, align 8, !align !1
+  %l.2 = load ptr, ptr %p, align 8, !align !1, !noundef !{}
   ret ptr %l.2
 }
 
@@ -70,12 +88,12 @@ define ptr @align_replacement_has_larger_alignment(ptr %p) {
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:    [[L_1:%.*]] = load ptr, ptr [[P]], align 8, !align [[META1:![0-9]+]]
 ; CHECK-NEXT:    call void @foo(ptr [[L_1]])
-; CHECK-NEXT:    [[L_2:%.*]] = load ptr, ptr [[P]], align 8, !align [[META0]]
+; CHECK-NEXT:    [[L_2:%.*]] = load ptr, ptr [[P]], align 8, !align [[META0]], !noundef [[META2:![0-9]+]]
 ; CHECK-NEXT:    ret ptr [[L_2]]
 ;
   %l.1 = load ptr, ptr %p, align 8, !align !1
   call void @foo(ptr %l.1)
-  %l.2 = load ptr, ptr %p, align 8, !align !0
+  %l.2 = load ptr, ptr %p, align 8, !align !0, !noundef !{}
   ret ptr %l.2
 }
 
@@ -84,12 +102,12 @@ define ptr @align_1(ptr %p) {
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:    [[L_1:%.*]] = load ptr, ptr [[P]], align 8
 ; CHECK-NEXT:    call void @foo(ptr [[L_1]])
-; CHECK-NEXT:    [[L_2:%.*]] = load ptr, ptr [[P]], align 8, !align [[META2:![0-9]+]]
+; CHECK-NEXT:    [[L_2:%.*]] = load ptr, ptr [[P]], align 8, !align [[META3:![0-9]+]], !noundef [[META2]]
 ; CHECK-NEXT:    ret ptr [[L_2]]
 ;
   %l.1 = load ptr, ptr %p, align 8
   call void @foo(ptr %l.1)
-  %l.2 = load ptr, ptr %p, align 8, !align !2
+  %l.2 = load ptr, ptr %p, align 8, !align !2, !noundef !{}
   ret ptr %l.2
 }
 
@@ -99,5 +117,6 @@ define ptr @align_1(ptr %p) {
 ;.
 ; CHECK: [[META0]] = !{i64 4}
 ; CHECK: [[META1]] = !{i64 8}
-; CHECK: [[META2]] = !{i64 1}
+; CHECK: [[META2]] = !{}
+; CHECK: [[META3]] = !{i64 1}
 ;.



More information about the llvm-commits mailing list