[llvm] 7203286 - [LangRef] vscale_range implies the vscale is power-of-two

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 14 18:18:05 PDT 2023


Author: Zhongyunde
Date: 2023-07-15T09:13:48+08:00
New Revision: 7203286329defc7976c719d8750712c0d5de9c31

URL: https://github.com/llvm/llvm-project/commit/7203286329defc7976c719d8750712c0d5de9c31
DIFF: https://github.com/llvm/llvm-project/commit/7203286329defc7976c719d8750712c0d5de9c31.diff

LOG: [LangRef] vscale_range implies the vscale is power-of-two

According the discuss on D154953, we need to make the LangRef change
before the optimization relied on the new behaviour:
      vscale_range implies vscale is a power-of-two value, parse of the
  attribute to reject values that are not a power-of-two.

Thanks nikic for the wonderful summary of discussing on D154953:
To provide a bit more context here. We would like to have power of two vscale exposed in a target-independent way, so we can make use of this in places like ValueTracking, just like we currently do the vscale range. Some options that have been discussed are:
  - Remove support for non-power-of-two vscales entirely. (This is my personal preference, but this is hard to undo if it turns out someone does need them.)
  - Add an extra attribute vscale_pow2, or a data layout property.
  - Make vscale_range imply power-of-two vscale, as a compromise solution (what this patch does). This would be relatively easy to turn into one of the two above at a later point.

Reviewed By: paulwalker-arm, nikic, efriedma
Differential Revision: https://reviews.llvm.org/D155193

Added: 
    

Modified: 
    llvm/docs/LangRef.rst
    llvm/lib/IR/Verifier.cpp
    llvm/test/Transforms/InstCombine/icmp-vscale.ll
    llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll
    llvm/test/Transforms/InstCombine/vscale_trunc.ll
    llvm/test/Verifier/vscale_range.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 1aae6852a3e16d..eeba36e4167323 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2331,11 +2331,12 @@ example:
     than `UINT_MAX`.  It's unspecified which threshold will be used when
     duplicate definitions are linked together with 
diff ering values.
 ``vscale_range(<min>[, <max>])``
-    This attribute indicates the minimum and maximum vscale value for the given
-    function. The min must be greater than 0. A maximum value of 0 means
-    unbounded. If the optional max value is omitted then max is set to the
-    value of min. If the attribute is not present, no assumptions are made
-    about the range of vscale.
+    This function attribute indicates `vscale` is a power-of-two within a
+    specified range. `min` must be a power-of-two that is greater than 0. When
+    specified, `max` must be a power-of-two greater-than-or-equal to `min` or 0
+    to signify an unbounded maximum. The syntax `vscale_range(<val>)` can be
+    used to set both `min` and `max` to the same value. Functions that don't
+    include this attribute make no assumptions about the value of `vscale`.
 ``"nooutline"``
     This attribute indicates that outlining passes should not modify the
     function.

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index d10eb5f4f03ee6..1408ce293ca654 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2181,10 +2181,13 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
     unsigned VScaleMin = Attrs.getFnAttrs().getVScaleRangeMin();
     if (VScaleMin == 0)
       CheckFailed("'vscale_range' minimum must be greater than 0", V);
-
+    else if (!isPowerOf2_32(VScaleMin))
+      CheckFailed("'vscale_range' minimum must be power-of-two value", V);
     std::optional<unsigned> VScaleMax = Attrs.getFnAttrs().getVScaleRangeMax();
     if (VScaleMax && VScaleMin > VScaleMax)
       CheckFailed("'vscale_range' minimum cannot be greater than maximum", V);
+    else if (VScaleMax && !isPowerOf2_32(*VScaleMax))
+      CheckFailed("'vscale_range' maximum must be power-of-two value", V);
   }
 
   if (Attrs.hasFnAttr("frame-pointer")) {

diff  --git a/llvm/test/Transforms/InstCombine/icmp-vscale.ll b/llvm/test/Transforms/InstCombine/icmp-vscale.ll
index baac5ce4959859..ae1be58938aa33 100644
--- a/llvm/test/Transforms/InstCombine/icmp-vscale.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-vscale.ll
@@ -82,85 +82,85 @@ entry:
   ret i1 %res
 }
 
-define i1 @vscale_ule_max() vscale_range(5,10) {
+define i1 @vscale_ule_max() vscale_range(4,8) {
 ; CHECK-LABEL: @vscale_ule_max(
 ; CHECK-NEXT:    ret i1 true
 ;
   %vscale = call i16 @llvm.vscale.i16()
-  %res = icmp ule i16 %vscale, 10
+  %res = icmp ule i16 %vscale, 8
   ret i1 %res
 }
 
-define i1 @vscale_ult_max() vscale_range(5,10) {
+define i1 @vscale_ult_max() vscale_range(4,8) {
 ; CHECK-LABEL: @vscale_ult_max(
 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i16 @llvm.vscale.i16()
-; CHECK-NEXT:    [[RES:%.*]] = icmp ult i16 [[VSCALE]], 10
+; CHECK-NEXT:    [[RES:%.*]] = icmp ult i16 [[VSCALE]], 8
 ; CHECK-NEXT:    ret i1 [[RES]]
 ;
   %vscale = call i16 @llvm.vscale.i16()
-  %res = icmp ult i16 %vscale, 10
+  %res = icmp ult i16 %vscale, 8
   ret i1 %res
 }
 
-define i1 @vscale_uge_min() vscale_range(5,10) {
+define i1 @vscale_uge_min() vscale_range(4,8) {
 ; CHECK-LABEL: @vscale_uge_min(
 ; CHECK-NEXT:    ret i1 true
 ;
   %vscale = call i16 @llvm.vscale.i16()
-  %res = icmp uge i16 %vscale, 5
+  %res = icmp uge i16 %vscale, 4
   ret i1 %res
 }
 
-define i1 @vscale_ugt_min() vscale_range(5,10) {
+define i1 @vscale_ugt_min() vscale_range(4,8) {
 ; CHECK-LABEL: @vscale_ugt_min(
 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i16 @llvm.vscale.i16()
-; CHECK-NEXT:    [[RES:%.*]] = icmp ugt i16 [[VSCALE]], 5
+; CHECK-NEXT:    [[RES:%.*]] = icmp ugt i16 [[VSCALE]], 4
 ; CHECK-NEXT:    ret i1 [[RES]]
 ;
   %vscale = call i16 @llvm.vscale.i16()
-  %res = icmp ugt i16 %vscale, 5
+  %res = icmp ugt i16 %vscale, 4
   ret i1 %res
 }
 
-define i1 @vscale_uge_no_max() vscale_range(5) {
+define i1 @vscale_uge_no_max() vscale_range(4) {
 ; CHECK-LABEL: @vscale_uge_no_max(
 ; CHECK-NEXT:    ret i1 true
 ;
   %vscale = call i8 @llvm.vscale.i8()
-  %res = icmp uge i8 %vscale, 5
+  %res = icmp uge i8 %vscale, 4
   ret i1 %res
 }
 
-define i1 @vscale_ugt_no_max() vscale_range(5) {
+define i1 @vscale_ugt_no_max() vscale_range(4) {
 ; CHECK-LABEL: @vscale_ugt_no_max(
 ; CHECK-NEXT:    ret i1 false
 ;
   %vscale = call i8 @llvm.vscale.i8()
-  %res = icmp ugt i8 %vscale, 5
+  %res = icmp ugt i8 %vscale, 4
   ret i1 %res
 }
 
-define i1 @vscale_uge_max_overflow() vscale_range(5,256) {
+define i1 @vscale_uge_max_overflow() vscale_range(4,256) {
 ; CHECK-LABEL: @vscale_uge_max_overflow(
 ; CHECK-NEXT:    ret i1 true
 ;
   %vscale = call i8 @llvm.vscale.i8()
-  %res = icmp uge i8 %vscale, 5
+  %res = icmp uge i8 %vscale, 4
   ret i1 %res
 }
 
-define i1 @vscale_ugt_max_overflow() vscale_range(5,256) {
+define i1 @vscale_ugt_max_overflow() vscale_range(4,256) {
 ; CHECK-LABEL: @vscale_ugt_max_overflow(
 ; CHECK-NEXT:    [[VSCALE:%.*]] = call i8 @llvm.vscale.i8()
-; CHECK-NEXT:    [[RES:%.*]] = icmp ugt i8 [[VSCALE]], 5
+; CHECK-NEXT:    [[RES:%.*]] = icmp ugt i8 [[VSCALE]], 4
 ; CHECK-NEXT:    ret i1 [[RES]]
 ;
   %vscale = call i8 @llvm.vscale.i8()
-  %res = icmp ugt i8 %vscale, 5
+  %res = icmp ugt i8 %vscale, 4
   ret i1 %res
 }
 
-define i1 @vscale_eq_min_overflow() vscale_range(256,300) {
+define i1 @vscale_eq_min_overflow() vscale_range(256,512) {
 ; CHECK-LABEL: @vscale_eq_min_overflow(
 ; CHECK-NEXT:    ret i1 true
 ;
@@ -169,7 +169,7 @@ define i1 @vscale_eq_min_overflow() vscale_range(256,300) {
   ret i1 %res
 }
 
-define i1 @vscale_ult_min_overflow() vscale_range(256,300) {
+define i1 @vscale_ult_min_overflow() vscale_range(256,512) {
 ; CHECK-LABEL: @vscale_ult_min_overflow(
 ; CHECK-NEXT:    ret i1 true
 ;
@@ -178,7 +178,7 @@ define i1 @vscale_ult_min_overflow() vscale_range(256,300) {
   ret i1 %res
 }
 
-define i1 @vscale_ugt_min_overflow() vscale_range(256,300) {
+define i1 @vscale_ugt_min_overflow() vscale_range(256,512) {
 ; CHECK-LABEL: @vscale_ugt_min_overflow(
 ; CHECK-NEXT:    ret i1 true
 ;

diff  --git a/llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll b/llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll
index aa224c11ae2f34..80d196d05735d2 100644
--- a/llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll
+++ b/llvm/test/Transforms/InstCombine/vscale_sext_and_zext.ll
@@ -5,7 +5,7 @@
 ; Sign-extend
 ;
 
-define i32 @vscale_SExt_i8toi32() vscale_range(1, 127) {
+define i32 @vscale_SExt_i8toi32() vscale_range(1, 64) {
 ; CHECK-LABEL: @vscale_SExt_i8toi32(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.vscale.i32()

diff  --git a/llvm/test/Transforms/InstCombine/vscale_trunc.ll b/llvm/test/Transforms/InstCombine/vscale_trunc.ll
index e7e416eaf78187..e5211ba6228cd4 100644
--- a/llvm/test/Transforms/InstCombine/vscale_trunc.ll
+++ b/llvm/test/Transforms/InstCombine/vscale_trunc.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
-define i8 @vscale_trunc_i32toi8() vscale_range(1, 255) {
+define i8 @vscale_trunc_i32toi8() vscale_range(1, 128) {
 ; CHECK-LABEL: @vscale_trunc_i32toi8(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.vscale.i8()

diff  --git a/llvm/test/Verifier/vscale_range.ll b/llvm/test/Verifier/vscale_range.ll
index 37e761e7464d4c..fc7abd7af1d82a 100644
--- a/llvm/test/Verifier/vscale_range.ll
+++ b/llvm/test/Verifier/vscale_range.ll
@@ -5,3 +5,9 @@ declare ptr @a(ptr) vscale_range(0, 1)
 
 ; CHECK: 'vscale_range' minimum cannot be greater than maximum
 declare ptr @b(ptr) vscale_range(8, 1)
+
+; CHECK: 'vscale_range' minimum must be power-of-two value
+declare ptr @c(ptr) vscale_range(3, 16)
+
+; CHECK: 'vscale_range' maximum must be power-of-two value
+declare ptr @d(ptr) vscale_range(2, 5)


        


More information about the llvm-commits mailing list