Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
Expand Down Expand Up @@ -1586,12 +1587,29 @@ static void computeKnownBitsFromOperator(const Operator *I,
Known.Zero.setBitsFrom(32);
break;
case Intrinsic::riscv_vsetvli:
case Intrinsic::riscv_vsetvlimax:
// Assume that VL output is <= 65536.
// TODO: Take SEW and LMUL into account.
if (BitWidth > 17)
Known.Zero.setBitsFrom(17);
case Intrinsic::riscv_vsetvlimax: {
bool HasAVL = II->getIntrinsicID() == Intrinsic::riscv_vsetvli;
const ConstantRange Range = getVScaleRange(II->getFunction(), BitWidth);
uint64_t SEW = RISCVVType::decodeVSEW(
cast<ConstantInt>(II->getArgOperand(HasAVL))->getZExtValue());
RISCVII::VLMUL VLMUL = static_cast<RISCVII::VLMUL>(
cast<ConstantInt>(II->getArgOperand(1 + HasAVL))->getZExtValue());
// The Range is [Lower, Upper), so we need to subtract 1 here to get the
// real upper value.
uint64_t MaxVLEN =
(Range.getUpper().getZExtValue() - 1) * RISCV::RVVBitsPerBlock;
uint64_t MaxVL = MaxVLEN / RISCVVType::getSEWLMULRatio(SEW, VLMUL);

// Result of vsetvli must be not larger than AVL.
if (HasAVL)
if (auto *CI = dyn_cast<ConstantInt>(II->getArgOperand(0)))
MaxVL = std::min(MaxVL, CI->getZExtValue());

unsigned KnownZeroFirstBit = Log2_32(MaxVL) + 1;
if (BitWidth > KnownZeroFirstBit)
Known.Zero.setBitsFrom(KnownZeroFirstBit);
break;
}
case Intrinsic::vscale: {
if (!II->getParent() || !II->getFunction())
break;
Expand Down
84 changes: 28 additions & 56 deletions llvm/test/Transforms/InstCombine/RISCV/riscv-vsetvli-knownbits.ll
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ entry:
define i64 @vsetvl_e8m1_and14bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e8m1_and14bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 0, i64 0)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 16383
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 0, i64 0)
%b = and i64 %a, 16383
Expand All @@ -113,8 +112,7 @@ define i64 @vsetvl_e8m1_and13bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e8m1_constant_avl() nounwind #0 {
; CHECK-LABEL: @vsetvl_e8m1_constant_avl(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 1, i64 0, i64 0)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 1
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 1, i64 0, i64 0)
%b = and i64 %a, 1
Expand All @@ -124,8 +122,7 @@ define i64 @vsetvl_e8m1_constant_avl() nounwind #0 {
define i64 @vsetvl_e8m2_and15bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e8m2_and15bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 0, i64 1)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 32767
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 0, i64 1)
%b = and i64 %a, 32767
Expand All @@ -146,8 +143,7 @@ define i64 @vsetvl_e8m2_and14bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e8m4_and16bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e8m4_and16bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 0, i64 2)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 65535
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 0, i64 2)
%b = and i64 %a, 65535
Expand Down Expand Up @@ -189,8 +185,7 @@ define i64 @vsetvl_e8m8_and16bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e8mf2_and11bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e8mf2_and11bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 0, i64 5)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 2047
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 0, i64 5)
%b = and i64 %a, 2047
Expand All @@ -211,8 +206,7 @@ define i64 @vsetvl_e8mf2_and10bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e8mf4_and12bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e8mf4_and12bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 0, i64 6)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 4095
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 0, i64 6)
%b = and i64 %a, 4095
Expand All @@ -233,8 +227,7 @@ define i64 @vsetvl_e8mf4_and11bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e8mf8_and13bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e8mf8_and13bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 0, i64 7)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 8191
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 0, i64 7)
%b = and i64 %a, 8191
Expand All @@ -255,8 +248,7 @@ define i64 @vsetvl_e8mf8_and12bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e16m1_and13bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e16m1_and13bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 1, i64 0)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 8191
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 1, i64 0)
%b = and i64 %a, 8191
Expand All @@ -277,8 +269,7 @@ define i64 @vsetvl_e16m1_and12bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e16m2_and14bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e16m2_and14bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 1, i64 1)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 16383
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 1, i64 1)
%b = and i64 %a, 16383
Expand All @@ -299,8 +290,7 @@ define i64 @vsetvl_e16m2_and13bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e16m4_and15bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e16m4_and15bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 1, i64 2)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 32767
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 1, i64 2)
%b = and i64 %a, 32767
Expand All @@ -321,8 +311,7 @@ define i64 @vsetvl_e16m4_and14bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e16m8_and16bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e16m8_and16bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 1, i64 3)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 65535
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 1, i64 3)
%b = and i64 %a, 65535
Expand All @@ -343,8 +332,7 @@ define i64 @vsetvl_e16m8_and15bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e16mf2_and10bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e16mf2_and10bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 1, i64 5)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 1023
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 1, i64 5)
%b = and i64 %a, 1023
Expand All @@ -365,8 +353,7 @@ define i64 @vsetvl_e16mf2_and9bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e16mf4_and11bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e16mf4_and11bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 1, i64 6)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 2047
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 1, i64 6)
%b = and i64 %a, 2047
Expand All @@ -387,8 +374,7 @@ define i64 @vsetvl_e16mf4_and10bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e16mf8_and12bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e16mf8_and12bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 1, i64 7)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 4095
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 1, i64 7)
%b = and i64 %a, 4095
Expand All @@ -409,8 +395,7 @@ define i64 @vsetvl_e16mf8_and11bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e32m1_and12bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e32m1_and12bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 2, i64 0)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 4095
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 0)
%b = and i64 %a, 4095
Expand All @@ -431,8 +416,7 @@ define i64 @vsetvl_e32m1_and11bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e32m2_and13bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e32m2_and13bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 2, i64 1)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 8191
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 1)
%b = and i64 %a, 8191
Expand All @@ -453,8 +437,7 @@ define i64 @vsetvl_e32m2_and12bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e32m4_and14bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e32m4_and14bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 2, i64 2)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 16383
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 2)
%b = and i64 %a, 16383
Expand All @@ -475,8 +458,7 @@ define i64 @vsetvl_e32m4_and13bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e32m8_and15bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e32m8_and15bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 2, i64 3)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 32767
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 3)
%b = and i64 %a, 32767
Expand All @@ -497,8 +479,7 @@ define i64 @vsetvl_e32m8_and14bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e32mf2_and9bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e32mf2_and9bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 2, i64 5)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 511
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 5)
%b = and i64 %a, 511
Expand All @@ -519,8 +500,7 @@ define i64 @vsetvl_e32mf2_and8bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e32mf4_and10bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e32mf4_and10bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 2, i64 6)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 1023
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 6)
%b = and i64 %a, 1023
Expand All @@ -541,8 +521,7 @@ define i64 @vsetvl_e32mf4_and9bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e32mf8_and11bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e32mf8_and11bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 2, i64 7)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 2047
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 2, i64 7)
%b = and i64 %a, 2047
Expand All @@ -563,8 +542,7 @@ define i64 @vsetvl_e32mf8_and10bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e64m1_and11bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e64m1_and11bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 3, i64 0)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 2047
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 0)
%b = and i64 %a, 2047
Expand All @@ -585,8 +563,7 @@ define i64 @vsetvl_e64m1_and10bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e64m2_and12bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e64m2_and12bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 3, i64 1)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 4095
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 1)
%b = and i64 %a, 4095
Expand All @@ -607,8 +584,7 @@ define i64 @vsetvl_e64m2_and11bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e64m4_and13bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e64m4_and13bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 3, i64 2)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 8191
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 2)
%b = and i64 %a, 8191
Expand All @@ -629,8 +605,7 @@ define i64 @vsetvl_e64m4_and12bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e64m8_and14bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e64m8_and14bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 3, i64 3)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 16383
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 3)
%b = and i64 %a, 16383
Expand All @@ -651,8 +626,7 @@ define i64 @vsetvl_e64m8_and13bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e64mf2_and8bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e64mf2_and8bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 3, i64 5)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 255
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 5)
%b = and i64 %a, 255
Expand All @@ -673,8 +647,7 @@ define i64 @vsetvl_e64mf2_and7bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e64mf4_and9bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e64mf4_and9bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 3, i64 6)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 511
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 6)
%b = and i64 %a, 511
Expand All @@ -695,8 +668,7 @@ define i64 @vsetvl_e64mf4_and8bits(i64 %avl) nounwind #0 {
define i64 @vsetvl_e64mf8_and10bits(i64 %avl) nounwind #0 {
; CHECK-LABEL: @vsetvl_e64mf8_and10bits(
; CHECK-NEXT: [[A:%.*]] = call i64 @llvm.riscv.vsetvli.i64(i64 [[AVL:%.*]], i64 3, i64 7)
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 1023
; CHECK-NEXT: ret i64 [[B]]
; CHECK-NEXT: ret i64 [[A]]
;
%a = call i64 @llvm.riscv.vsetvli(i64 %avl, i64 3, i64 7)
%b = and i64 %a, 1023
Expand Down
Loading