[llvm] [InstCombine] Swap out range metadata to range attribute for arm_mve_pred_v2i (PR #94847)

Andreas Jonson via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 9 12:49:25 PDT 2024


https://github.com/andjo403 updated https://github.com/llvm/llvm-project/pull/94847

>From 0a382449ff7cd750ca1ae5161140d9468a46bcf3 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 8 Jun 2024 11:05:26 +0200
Subject: [PATCH 1/2] [InstCombine] Swap out range metadata to range attribute
 for arm_mve_pred_v2i

---
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 20 +++++---
 .../SelectionDAG/SelectionDAGBuilder.h        |  2 +-
 .../lib/Target/ARM/ARMTargetTransformInfo.cpp | 25 +++++----
 .../Transforms/InstCombine/ARM/mve-v2i2v.ll   | 51 +++++++++++++++----
 4 files changed, 70 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index be5e0f6ef058b..21207ebe5c98b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10227,21 +10227,25 @@ void SelectionDAGBuilder::visitVACopy(const CallInst &I) {
 }
 
 SDValue SelectionDAGBuilder::lowerRangeToAssertZExt(SelectionDAG &DAG,
-                                                    const Instruction &I,
+                                                    const CallBase &I,
                                                     SDValue Op) {
-  const MDNode *Range = getRangeMetadata(I);
-  if (!Range)
-    return Op;
+  std::optional<ConstantRange> CR = I.getRange();
+  if (const MDNode *Range = getRangeMetadata(I)) {
+    ConstantRange R = getConstantRangeFromMetadata(*Range);
+    if (CR)
+      CR = CR->intersectWith(R);
+    else
+      CR = R;
+  }
 
-  ConstantRange CR = getConstantRangeFromMetadata(*Range);
-  if (CR.isFullSet() || CR.isEmptySet() || CR.isUpperWrapped())
+  if (!CR || CR->isFullSet() || CR->isEmptySet() || CR->isUpperWrapped())
     return Op;
 
-  APInt Lo = CR.getUnsignedMin();
+  APInt Lo = CR->getUnsignedMin();
   if (!Lo.isMinValue())
     return Op;
 
-  APInt Hi = CR.getUnsignedMax();
+  APInt Hi = CR->getUnsignedMax();
   unsigned Bits = std::max(Hi.getActiveBits(),
                            static_cast<unsigned>(IntegerType::MIN_INT_BITS));
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 1a98fbd7589fb..0f7bad27c4bba 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -411,7 +411,7 @@ class SelectionDAGBuilder {
 
   // Lower range metadata from 0 to N to assert zext to an integer of nearest
   // floor power of two.
-  SDValue lowerRangeToAssertZExt(SelectionDAG &DAG, const Instruction &I,
+  SDValue lowerRangeToAssertZExt(SelectionDAG &DAG, const CallBase &I,
                                  SDValue Op);
 
   void populateCallLoweringInfo(TargetLowering::CallLoweringInfo &CLI,
diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
index 7db2e8ee7e6f9..ec2bfb98832e4 100644
--- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
@@ -199,17 +199,22 @@ ARMTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
                        PatternMatch::m_Value(ArgArg)))) {
       return IC.replaceInstUsesWith(II, ArgArg);
     }
-    if (!II.getMetadata(LLVMContext::MD_range)) {
-      Type *IntTy32 = Type::getInt32Ty(II.getContext());
-      Metadata *M[] = {
-          ConstantAsMetadata::get(ConstantInt::get(IntTy32, 0)),
-          ConstantAsMetadata::get(ConstantInt::get(IntTy32, 0x10000))};
-      II.setMetadata(LLVMContext::MD_range, MDNode::get(II.getContext(), M));
-      II.setMetadata(LLVMContext::MD_noundef,
-                     MDNode::get(II.getContext(), std::nullopt));
-      return &II;
+
+    if (II.getMetadata(LLVMContext::MD_range))
+      break;
+
+    ConstantRange Range(APInt(32, 0), APInt(32, 0x10000));
+
+    if (auto CurrentRange = II.getRange()) {
+      Range = Range.intersectWith(*CurrentRange);
+      if (Range == CurrentRange)
+        break;
     }
-    break;
+
+    II.addRangeRetAttr(Range);
+    II.setMetadata(LLVMContext::MD_noundef,
+                   MDNode::get(II.getContext(), std::nullopt));
+    return &II;
   }
   case Intrinsic::arm_mve_vadc:
   case Intrinsic::arm_mve_vadc_predicated: {
diff --git a/llvm/test/Transforms/InstCombine/ARM/mve-v2i2v.ll b/llvm/test/Transforms/InstCombine/ARM/mve-v2i2v.ll
index d0d17efd23050..2d8e8096efcf1 100644
--- a/llvm/test/Transforms/InstCombine/ARM/mve-v2i2v.ll
+++ b/llvm/test/Transforms/InstCombine/ARM/mve-v2i2v.ll
@@ -66,7 +66,7 @@ entry:
 define <16 x i1> @v2i2v_2_16(<2 x i1> %vin) {
 ; CHECK-LABEL: @v2i2v_2_16(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[INT:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v2i1(<2 x i1> [[VIN:%.*]]), !range [[RNG0:![0-9]+]]
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v2i1(<2 x i1> [[VIN:%.*]]), !noundef [[META0:![0-9]+]]
 ; CHECK-NEXT:    [[VOUT:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[INT]])
 ; CHECK-NEXT:    ret <16 x i1> [[VOUT]]
 ;
@@ -79,7 +79,7 @@ entry:
 define <16 x i1> @v2i2v_4_16(<4 x i1> %vin) {
 ; CHECK-LABEL: @v2i2v_4_16(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[INT:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    [[VOUT:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[INT]])
 ; CHECK-NEXT:    ret <16 x i1> [[VOUT]]
 ;
@@ -92,7 +92,7 @@ entry:
 define <4 x i1> @v2i2v_8_4(<8 x i1> %vin) {
 ; CHECK-LABEL: @v2i2v_8_4(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[INT:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    [[VOUT:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[INT]])
 ; CHECK-NEXT:    ret <4 x i1> [[VOUT]]
 ;
@@ -105,7 +105,7 @@ entry:
 define <8 x i1> @v2i2v_16_8(<16 x i1> %vin) {
 ; CHECK-LABEL: @v2i2v_16_8(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[INT:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    [[VOUT:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[INT]])
 ; CHECK-NEXT:    ret <8 x i1> [[VOUT]]
 ;
@@ -170,7 +170,7 @@ entry:
 define i32 @v2i_truncext_i16(<4 x i1> %vin) {
 ; CHECK-LABEL: @v2i_truncext_i16(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[WIDE1:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    ret i32 [[WIDE1]]
 ;
 entry:
@@ -183,7 +183,7 @@ entry:
 define i32 @v2i_truncext_i8(<4 x i1> %vin) {
 ; CHECK-LABEL: @v2i_truncext_i8(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[WIDE1:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    [[WIDE2:%.*]] = and i32 [[WIDE1]], 255
 ; CHECK-NEXT:    ret i32 [[WIDE2]]
 ;
@@ -197,7 +197,7 @@ entry:
 define i32 @v2i_and_16(<4 x i1> %vin) {
 ; CHECK-LABEL: @v2i_and_16(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[WIDE1:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    ret i32 [[WIDE1]]
 ;
 entry:
@@ -209,7 +209,7 @@ entry:
 define i32 @v2i_and_15(<4 x i1> %vin) {
 ; CHECK-LABEL: @v2i_and_15(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[WIDE1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[WIDE1:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    [[WIDE2:%.*]] = and i32 [[WIDE1]], 32767
 ; CHECK-NEXT:    ret i32 [[WIDE2]]
 ;
@@ -397,7 +397,7 @@ entry:
 define i32 @range_upper_limit(<16 x i1> %vin) {
 ; CHECK-LABEL: @range_upper_limit(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[INT:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> [[VIN:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> [[VIN:%.*]]), !noundef [[META0]]
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[INT]], 65535
 ; CHECK-NEXT:    [[S:%.*]] = zext i1 [[C]] to i32
 ; CHECK-NEXT:    ret i32 [[S]]
@@ -408,3 +408,36 @@ entry:
   %s = select i1 %c, i32 1, i32 0
   ret i32 %s
 }
+
+define i32 @range_already_added_larger_range(<16 x i1> %vin) {
+; CHECK-LABEL: @range_already_added_larger_range(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> [[VIN:%.*]]), !noundef [[META0]]
+; CHECK-NEXT:    ret i32 [[INT]]
+;
+entry:
+  %int = call range(i32 0, 65540) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> %vin), !noundef !{}
+  ret i32 %int
+}
+
+define i32 @range_already_added_smaller_range(<16 x i1> %vin) {
+; CHECK-LABEL: @range_already_added_smaller_range(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 655) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> [[VIN:%.*]]), !noundef [[META0]]
+; CHECK-NEXT:    ret i32 [[INT]]
+;
+entry:
+  %int = call range(i32 0, 655) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> %vin), !noundef !{}
+  ret i32 %int
+}
+
+define i32 @range_already_added_same_range(<16 x i1> %vin) {
+; CHECK-LABEL: @range_already_added_same_range(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INT:%.*]] = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> [[VIN:%.*]]), !noundef [[META0]]
+; CHECK-NEXT:    ret i32 [[INT]]
+;
+entry:
+  %int = call range(i32 0, 65536) i32 @llvm.arm.mve.pred.v2i.v16i1(<16 x i1> %vin), !noundef !{}
+  ret i32 %int
+}

>From e6e8335b5475792f55180db5a9308be4135199f4 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sun, 9 Jun 2024 21:35:33 +0200
Subject: [PATCH 2/2] fixup! [InstCombine] Swap out range metadata to range
 attribute for arm_mve_pred_v2i

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 7 +++++--
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h   | 2 +-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 21207ebe5c98b..ebc224b37b20c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10227,9 +10227,12 @@ void SelectionDAGBuilder::visitVACopy(const CallInst &I) {
 }
 
 SDValue SelectionDAGBuilder::lowerRangeToAssertZExt(SelectionDAG &DAG,
-                                                    const CallBase &I,
+                                                    const Instruction &I,
                                                     SDValue Op) {
-  std::optional<ConstantRange> CR = I.getRange();
+  std::optional<ConstantRange> CR;
+  if (const auto *CB = dyn_cast<CallBase>(&I))
+    CR = CB->getRange();
+
   if (const MDNode *Range = getRangeMetadata(I)) {
     ConstantRange R = getConstantRangeFromMetadata(*Range);
     if (CR)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 0f7bad27c4bba..1a98fbd7589fb 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -411,7 +411,7 @@ class SelectionDAGBuilder {
 
   // Lower range metadata from 0 to N to assert zext to an integer of nearest
   // floor power of two.
-  SDValue lowerRangeToAssertZExt(SelectionDAG &DAG, const CallBase &I,
+  SDValue lowerRangeToAssertZExt(SelectionDAG &DAG, const Instruction &I,
                                  SDValue Op);
 
   void populateCallLoweringInfo(TargetLowering::CallLoweringInfo &CLI,



More information about the llvm-commits mailing list