Skip to content

Commit acb4f2a

Browse files
[EVM][ConstantRange] Add support for signextend intrinsic
Signed-off-by: Vladimir Radosavljevic <[email protected]>
1 parent bcc88e0 commit acb4f2a

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

llvm/include/llvm/IR/ConstantRange.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ class [[nodiscard]] ConstantRange {
554554
/// Calculate ctpop range.
555555
ConstantRange ctpop() const;
556556

557+
ConstantRange evmSignExtend(const ConstantRange &Other) const;
558+
557559
/// Represents whether an operation on the given constant range is known to
558560
/// always or never overflow.
559561
enum class OverflowResult {

llvm/include/llvm/IR/IntrinsicsEVM.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ def int_evm_sha3
9191
NoCapture<ArgIndex<0>>, IntrWillReturn]>;
9292

9393
def int_evm_signextend
94-
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty],
95-
[IntrNoMem, IntrWillReturn]>;
94+
: DefaultAttrsIntrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty],
95+
[IntrNoMem, IntrSpeculatable]>;
9696

9797
def int_evm_byte : Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty],
9898
[IntrNoMem, IntrWillReturn]>;

llvm/lib/IR/ConstantRange.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/IR/InstrTypes.h"
2828
#include "llvm/IR/Instruction.h"
2929
#include "llvm/IR/Intrinsics.h"
30+
#include "llvm/IR/IntrinsicsEVM.h"
3031
#include "llvm/IR/Metadata.h"
3132
#include "llvm/IR/Operator.h"
3233
#include "llvm/Support/Compiler.h"
@@ -1009,6 +1010,7 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID IntrinsicID) {
10091010
case Intrinsic::ctlz:
10101011
case Intrinsic::cttz:
10111012
case Intrinsic::ctpop:
1013+
case Intrinsic::evm_signextend:
10121014
return true;
10131015
default:
10141016
return false;
@@ -1018,6 +1020,8 @@ bool ConstantRange::isIntrinsicSupported(Intrinsic::ID IntrinsicID) {
10181020
ConstantRange ConstantRange::intrinsic(Intrinsic::ID IntrinsicID,
10191021
ArrayRef<ConstantRange> Ops) {
10201022
switch (IntrinsicID) {
1023+
case Intrinsic::evm_signextend:
1024+
return Ops[0].evmSignExtend(Ops[1]);
10211025
case Intrinsic::uadd_sat:
10221026
return Ops[0].uadd_sat(Ops[1]);
10231027
case Intrinsic::usub_sat:
@@ -1953,6 +1957,26 @@ ConstantRange ConstantRange::ctpop() const {
19531957
return CR1.unionWith(CR2);
19541958
}
19551959

1960+
ConstantRange ConstantRange::evmSignExtend(const ConstantRange &Other) const {
1961+
unsigned BitWidth = getBitWidth();
1962+
if (BitWidth != 256)
1963+
return getFull();
1964+
1965+
if (isEmptySet() || Other.isEmptySet())
1966+
return getEmpty();
1967+
1968+
if (!isSingleElement())
1969+
return getFull();
1970+
1971+
// ByteIdx must be in range [0, 31].
1972+
uint64_t ByteIdx = getSingleElement()->getZExtValue();
1973+
if (ByteIdx >= BitWidth / 8)
1974+
return getFull();
1975+
1976+
unsigned Width = (ByteIdx + 1) * 8;
1977+
return Other.truncate(Width).signExtend(BitWidth);
1978+
}
1979+
19561980
ConstantRange::OverflowResult ConstantRange::unsignedAddMayOverflow(
19571981
const ConstantRange &Other) const {
19581982
if (isEmptySet() || Other.isEmptySet())

0 commit comments

Comments
 (0)