Skip to content

Commit f9bd876

Browse files
[EVM][ValueTracking] Add support for signextend intrinsic
Signed-off-by: Vladimir Radosavljevic <[email protected]>
1 parent 772076f commit f9bd876

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "llvm/IR/Intrinsics.h"
5858
#include "llvm/IR/IntrinsicsAArch64.h"
5959
#include "llvm/IR/IntrinsicsAMDGPU.h"
60+
#include "llvm/IR/IntrinsicsEVM.h"
6061
#include "llvm/IR/IntrinsicsRISCV.h"
6162
#include "llvm/IR/IntrinsicsX86.h"
6263
#include "llvm/IR/LLVMContext.h"
@@ -3740,6 +3741,28 @@ static unsigned computeNumSignBitsVectorConstant(const Value *V,
37403741
return MinSignBits;
37413742
}
37423743

3744+
static unsigned computeNumSignBitsForEVMSignExtend(const IntrinsicInst *II) {
3745+
auto *Ty = dyn_cast<IntegerType>(II->getType());
3746+
if (!Ty)
3747+
return 1;
3748+
3749+
unsigned BitWidth = Ty->getIntegerBitWidth();
3750+
if (BitWidth != 256)
3751+
return 1;
3752+
3753+
const auto *ByteIdxC = dyn_cast<ConstantInt>(II->getArgOperand(0));
3754+
if (!ByteIdxC)
3755+
return 1;
3756+
3757+
// ByteIdx must be in range [0, 31].
3758+
uint64_t ByteIdx = ByteIdxC->getZExtValue();
3759+
if (ByteIdx >= BitWidth / 8)
3760+
return 1;
3761+
3762+
unsigned Width = (ByteIdx + 1) * 8;
3763+
return BitWidth - Width + 1;
3764+
}
3765+
37433766
static unsigned ComputeNumSignBitsImpl(const Value *V,
37443767
const APInt &DemandedElts,
37453768
unsigned Depth, const SimplifyQuery &Q);
@@ -4070,6 +4093,8 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
40704093
switch (II->getIntrinsicID()) {
40714094
default:
40724095
break;
4096+
case Intrinsic::evm_signextend:
4097+
return computeNumSignBitsForEVMSignExtend(II);
40734098
case Intrinsic::abs:
40744099
Tmp =
40754100
ComputeNumSignBits(U->getOperand(0), DemandedElts, Depth + 1, Q);
@@ -9509,10 +9534,35 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
95099534
}
95109535
}
95119536

9537+
static ConstantRange getRangeForEVMSignExtend(const IntrinsicInst &II) {
9538+
unsigned BitWidth = II.getType()->getIntegerBitWidth();
9539+
if (BitWidth != 256)
9540+
return ConstantRange::getFull(BitWidth);
9541+
9542+
auto *ByteIdxC = dyn_cast<ConstantInt>(II.getArgOperand(0));
9543+
if (!ByteIdxC)
9544+
return ConstantRange::getFull(BitWidth);
9545+
9546+
// ByteIdx must be in range [0, 31].
9547+
uint64_t ByteIdx = ByteIdxC->getZExtValue();
9548+
if (ByteIdx >= BitWidth / 8)
9549+
return ConstantRange::getFull(BitWidth);
9550+
9551+
// Range that signextend produces is:
9552+
// [ -2^(width-1), 2^(width-1)-1 ] in signed space
9553+
// Since ConstantRange is [Min, Max), and Max is exclusive, we need to add 1.
9554+
unsigned Width = (ByteIdx + 1) * 8;
9555+
return ConstantRange::getNonEmpty(
9556+
APInt::getSignedMinValue(Width).sext(BitWidth),
9557+
APInt::getSignedMaxValue(Width).sext(BitWidth) + 1);
9558+
}
9559+
95129560
static ConstantRange getRangeForIntrinsic(const IntrinsicInst &II) {
95139561
unsigned Width = II.getType()->getScalarSizeInBits();
95149562
const APInt *C;
95159563
switch (II.getIntrinsicID()) {
9564+
case Intrinsic::evm_signextend:
9565+
return getRangeForEVMSignExtend(II);
95169566
case Intrinsic::ctpop:
95179567
case Intrinsic::ctlz:
95189568
case Intrinsic::cttz:

0 commit comments

Comments
 (0)