Skip to content

Commit 8ef1203

Browse files
Add more support for signextend
Signed-off-by: Vladimir Radosavljevic <[email protected]>
1 parent 06c60cd commit 8ef1203

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,6 +1630,30 @@ static void computeKnownBitsFromOperator(const Operator *I,
16301630
switch (II->getIntrinsicID()) {
16311631
default:
16321632
break;
1633+
case Intrinsic::evm_signextend: {
1634+
auto *Ty = dyn_cast<IntegerType>(II->getType());
1635+
if (!Ty)
1636+
break;
1637+
1638+
unsigned BitWidth = Ty->getIntegerBitWidth();
1639+
if (BitWidth != 256)
1640+
break;
1641+
1642+
const auto *ByteIdxC = dyn_cast<ConstantInt>(II->getArgOperand(0));
1643+
if (!ByteIdxC)
1644+
break;
1645+
1646+
// ByteIdx must be in range [0, 31].
1647+
uint64_t ByteIdx = ByteIdxC->getZExtValue();
1648+
if (ByteIdx >= BitWidth / 8)
1649+
break;
1650+
1651+
computeKnownBits(I->getOperand(1), DemandedElts, Known2, Depth + 1, Q);
1652+
unsigned Width = (ByteIdx + 1) * 8;
1653+
Known = Known2.trunc(Width).sext(BitWidth);
1654+
break;
1655+
}
1656+
16331657
case Intrinsic::abs: {
16341658
computeKnownBits(I->getOperand(0), DemandedElts, Known2, Depth + 1, Q);
16351659
bool IntMinIsPoison = match(II->getArgOperand(1), m_One());
@@ -3185,6 +3209,8 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
31853209
return true;
31863210
case Intrinsic::experimental_get_vector_length:
31873211
return isKnownNonZero(I->getOperand(0), Q, Depth);
3212+
case Intrinsic::evm_signextend:
3213+
return isKnownNonZero(II->getArgOperand(1), DemandedElts, Q, Depth);
31883214
default:
31893215
break;
31903216
}

llvm/lib/Target/EVM/EVMTargetTransformInfo.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,34 @@ using namespace llvm::PatternMatch;
1919

2020
#define DEBUG_TYPE "evmtti"
2121

22+
static std::optional<Instruction *> foldSignExtendToConst(InstCombiner &IC,
23+
IntrinsicInst &II) {
24+
constexpr unsigned BitWidth = 256;
25+
if (!II.getType()->isIntegerTy(BitWidth))
26+
return std::nullopt;
27+
28+
const auto *ByteIdxC = dyn_cast<ConstantInt>(II.getArgOperand(0));
29+
if (!ByteIdxC)
30+
return std::nullopt;
31+
32+
// ByteIdx must be in range [0, 31].
33+
uint64_t ByteIdx = ByteIdxC->getZExtValue();
34+
if (ByteIdx >= BitWidth / 8)
35+
return std::nullopt;
36+
37+
// Compute known bits of the input.
38+
KnownBits Known(BitWidth);
39+
IC.computeKnownBits(II.getArgOperand(1), Known, 0, &II);
40+
41+
unsigned Width = (ByteIdx + 1) * 8;
42+
APInt LowMask = APInt::getLowBitsSet(BitWidth, Width);
43+
if (((Known.Zero | Known.One) & LowMask) == LowMask) {
44+
APInt Folded = (Known.One & LowMask).trunc(Width).sext(BitWidth);
45+
return IC.replaceInstUsesWith(II, ConstantInt::get(II.getType(), Folded));
46+
}
47+
return std::nullopt;
48+
}
49+
2250
static std::optional<Instruction *> instCombineSignExtend(InstCombiner &IC,
2351
IntrinsicInst &II) {
2452
// Fold signextend(b, signextend(b, x)) -> signextend(b, x)
@@ -28,7 +56,7 @@ static std::optional<Instruction *> instCombineSignExtend(InstCombiner &IC,
2856
m_Deferred(B), m_Value(X)))))
2957
return IC.replaceInstUsesWith(II, II.getArgOperand(1));
3058

31-
return std::nullopt;
59+
return foldSignExtendToConst(IC, II);
3260
}
3361

3462
std::optional<Instruction *>

0 commit comments

Comments
 (0)