[PATCH] D67438: [InstCombine] Range metadata for ARM MVE VMIN/VMAX.

Simon Tatham via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 11 05:01:25 PDT 2019


simon_tatham created this revision.
simon_tatham added reviewers: dmgreen, miyuki, ostannard.
Herald added subscribers: llvm-commits, hiraditya, kristof.beyls.
Herald added a project: LLVM.

The VMINV and VMAXV intrinsics return a value of type i32. But it's
always going to be the sign- or zero-extension of a lane of its vector
operand, so if that lane is smaller than 32 bits, the i32 value will
often have a smaller range.

Setting range metadata on the output value should allow the backend to
avoid emitting an unnecessary UXTB or SXTB instruction if the user
code then casts the value back to the smaller vector-lane integer
type.

In fact, this seems to work in the unsigned case, but not in the
signed case, because `SelectionDAGBuilder::lowerRangeToAssertZExt`
doesn't come with a counterpart for AssertSExt. But if one is added in
future, then this commit will enable it to apply to VMIN and VMAX.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67438

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
  llvm/test/CodeGen/Thumb2/mve-intrinsics/vmin-instcombine.ll


Index: llvm/test/CodeGen/Thumb2/mve-intrinsics/vmin-instcombine.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/Thumb2/mve-intrinsics/vmin-instcombine.ll
@@ -0,0 +1,38 @@
+; RUN: opt -instcombine -S -o - %s | FileCheck --check-prefix=IR %s
+; RUN: opt -instcombine %s | llc -mtriple=thumbv8.1m.main -mattr=+mve.fp -verify-machineinstrs -o - | FileCheck --check-prefix=ASM %s
+
+define arm_aapcs_vfpcc i32 @test_vmaxvq_u8(i32 %a, <16 x i8> %b) {
+; ASM-LABEL: test_vmaxvq_u8:
+; ASM:       @ %bb.0: @ %entry
+; ASM-NEXT:    vmaxv.u8 r0, q0
+; ASM-NEXT:    bx lr
+entry:
+  %0 = tail call i32 @llvm.arm.mve.maxv.u.v16i8(i32 %a, <16 x i8> %b)
+  %1 = trunc i32 %0 to i8
+  %2 = zext i8 %1 to i32
+  ret i32 %2
+}
+
+define arm_aapcs_vfpcc i16 @test_vminvq_s16(i32 %a, <8 x i16> %b) {
+; ASM-LABEL: test_vminvq_s16:
+; ASM:       @ %bb.0: @ %entry
+; ASM-NEXT:    vminv.s16 r0, q0
+; Ideally the next line should be ASM-NEXT, enforcing that there's
+; no sxth instruction between the vminv and the return. But in fact
+; there is, because signed range metadata doesn't generate an
+; AssertSext.
+; ASM:    bx lr
+entry:
+  %0 = tail call i32 @llvm.arm.mve.minv.s.v8i16(i32 %a, <8 x i16> %b)
+  %1 = trunc i32 %0 to i16
+  %2 = sext i16 %1 to i32
+  ret i16 %1
+}
+
+declare i32 @llvm.arm.mve.maxv.u.v16i8(i32, <16 x i8>)
+declare i32 @llvm.arm.mve.minv.s.v8i16(i32, <8 x i16>)
+
+; IR: tail call i32 @llvm.arm.mve.maxv.u.v16i8(i32 %a, <16 x i8> %b), !range !0
+; IR: tail call i32 @llvm.arm.mve.minv.s.v8i16(i32 %a, <8 x i16> %b), !range !
+; IR: !0 = !{i32 0, i32 256}
+; IR: !1 = !{i32 -32768, i32 32768}
Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3298,6 +3298,39 @@
     }
     break;
   }
+  case Intrinsic::arm_mve_minv_u:
+  case Intrinsic::arm_mve_minv_s:
+  case Intrinsic::arm_mve_maxv_u:
+  case Intrinsic::arm_mve_maxv_s: {
+    unsigned ScalarWidth = II->getArgOperand(1)
+                               ->getType()
+                               ->getVectorElementType()
+                               ->getScalarSizeInBits();
+
+    bool Modified = false;
+
+    KnownBits ScalarKnown(32);
+    if (SimplifyDemandedBits(II, 0, APInt::getLowBitsSet(32, ScalarWidth),
+                             ScalarKnown, 0))
+      Modified = true;
+    if (ScalarWidth < 32 && !II->getMetadata(LLVMContext::MD_range)) {
+      uint32_t Lo = 0, Hi = (uint32_t)1 << ScalarWidth;
+      if (IID == Intrinsic::arm_mve_minv_s ||
+          IID == Intrinsic::arm_mve_maxv_s) {
+        uint32_t Offset = Hi >> 1;
+        Lo -= Offset;
+        Hi -= Offset;
+      }
+      Type *IntTy32 = Type::getInt32Ty(II->getContext());
+      Metadata *M[] = {ConstantAsMetadata::get(ConstantInt::get(IntTy32, Lo)),
+                       ConstantAsMetadata::get(ConstantInt::get(IntTy32, Hi))};
+      II->setMetadata(LLVMContext::MD_range, MDNode::get(II->getContext(), M));
+      Modified = true;
+    }
+    if (Modified)
+      return II;
+    break;
+  }
   case Intrinsic::arm_mve_vadc:
   case Intrinsic::arm_mve_vadc_predicated: {
     unsigned CarryOp =


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67438.219695.patch
Type: text/x-patch
Size: 3315 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190911/1a876512/attachment.bin>


More information about the llvm-commits mailing list