[llvm] [ConstantInt] Disable implicit truncation in ConstantInt::get() (PR #171456)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 9 07:26:29 PST 2025
https://github.com/nikic created https://github.com/llvm/llvm-project/pull/171456
Disable implicit truncation in the ConstantInt constructor by default. This means that it needs to be passed a signed/unsigned (depending on the IsSigned flag) value matching the bit width.
The intention is to prevent the recurring bug where people write something like `ConstantInt::get(Ty, -1)`, and this "works" until `Ty` is larger than 64-bit and then the value is incorrect due to missing type extension.
This is the continuation of https://github.com/llvm/llvm-project/pull/112670, which originally allowed implicit truncation in this constructor to reduce initial scope of the change.
This PR is WIP. Most parts will be landed separately.
>From c0fcb4d215fd81cbd6978409b5832f2c3c4d22f6 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 12:04:38 +0100
Subject: [PATCH 1/9] [IR] Disable implicit truncation in ConstantInt::get() by
default
---
llvm/include/llvm/IR/Constants.h | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 39a556abe935b..6aa79846f10f5 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -113,9 +113,8 @@ class ConstantInt final : public ConstantData {
/// If Ty is a vector type, return a Constant with a splat of the given
/// value. Otherwise return a ConstantInt for the given value.
/// \param ImplicitTrunc Whether to allow implicit truncation of the value.
- // TODO: Make ImplicitTrunc default to false.
LLVM_ABI static Constant *get(Type *Ty, uint64_t V, bool IsSigned = false,
- bool ImplicitTrunc = true);
+ bool ImplicitTrunc = false);
/// Return a ConstantInt with the specified integer value for the specified
/// type. If the type is wider than 64 bits, the value will be zero-extended
@@ -123,10 +122,9 @@ class ConstantInt final : public ConstantData {
/// be interpreted as a 64-bit signed integer and sign-extended to fit
/// the type.
/// \param ImplicitTrunc Whether to allow implicit truncation of the value.
- // TODO: Make ImplicitTrunc default to false.
LLVM_ABI static ConstantInt *get(IntegerType *Ty, uint64_t V,
bool IsSigned = false,
- bool ImplicitTrunc = true);
+ bool ImplicitTrunc = false);
/// Return a ConstantInt with the specified value for the specified type. The
/// value V will be canonicalized to an unsigned APInt. Accessing it with
>From db9c886fa52503b48d2f6ed227b14e90f1998c87 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 12:18:21 +0100
Subject: [PATCH 2/9] [SDAG] Allow implicit trunc in BUILD_VECTOR legalization
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 7606bc8f4a5b6..1552b6a1efa1c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2051,7 +2051,8 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
// we don't want a v16i8 to become a v16i32 for example.
const ConstantInt *CI = V->getConstantIntValue();
CV.push_back(ConstantInt::get(EltVT.getTypeForEVT(*DAG.getContext()),
- CI->getZExtValue()));
+ CI->getZExtValue(), /*IsSigned=*/false,
+ /*ImplicitTrunc=*/true));
}
} else {
assert(Node->getOperand(i).isUndef());
>From 3c1acdc1e90b2706901e912fab05b522356e4948 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 12:22:32 +0100
Subject: [PATCH 3/9] [SCEV] Allow implicit truncation for now, to reduce scope
---
llvm/lib/Analysis/ScalarEvolution.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index e1f90264be7a2..770de89eccfb9 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -485,7 +485,10 @@ const SCEV *ScalarEvolution::getConstant(const APInt &Val) {
const SCEV *
ScalarEvolution::getConstant(Type *Ty, uint64_t V, bool isSigned) {
IntegerType *ITy = cast<IntegerType>(getEffectiveSCEVType(Ty));
- return getConstant(ConstantInt::get(ITy, V, isSigned));
+ // TODO: Avoid implicit trunc?
+ // See https://github.com/llvm/llvm-project/issues/112510.
+ return getConstant(
+ ConstantInt::get(ITy, V, isSigned, /*ImplicitTrunc=*/true));
}
const SCEV *ScalarEvolution::getVScale(Type *Ty) {
>From 85d47a931d17452dda9ff0118d2a2a9e13998552 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 12:43:29 +0100
Subject: [PATCH 4/9] [MachineIRBuilder] Allow implicit trunc for now
To limit scope.
---
llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 3906b311addf0..f4779d9a122f0 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -363,7 +363,10 @@ MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
int64_t Val) {
auto IntN = IntegerType::get(getMF().getFunction().getContext(),
Res.getLLTTy(*getMRI()).getScalarSizeInBits());
- ConstantInt *CI = ConstantInt::get(IntN, Val, true);
+ // TODO: Avoid implicit trunc?
+ // See https://github.com/llvm/llvm-project/issues/112510.
+ ConstantInt *CI =
+ ConstantInt::get(IntN, Val, /*isSigned=*/true, /*implicitTrunc=*/true);
return buildConstant(Res, *CI);
}
>From edfd05804b1c0cc75cc0fc8d38bf1bb1657fa122 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 13:00:02 +0100
Subject: [PATCH 5/9] [ExpandFp] Adjust ConstantInt construction (NFC)
This makes two changes:
* In one place, explicitly cast to int before negating, so that
the value is sign extended, and getSigned() is actually passed
a value with all the sign bits set.
* Use getSignMask() to create the 32-bit sign mask.
This avoids issues with a future assertion in the ConstantInt
ctor.
---
llvm/lib/CodeGen/ExpandFp.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/ExpandFp.cpp b/llvm/lib/CodeGen/ExpandFp.cpp
index 13ed4846d2bf7..5941c41cd743f 100644
--- a/llvm/lib/CodeGen/ExpandFp.cpp
+++ b/llvm/lib/CodeGen/ExpandFp.cpp
@@ -811,7 +811,7 @@ static void expandIToFP(Instruction *IToFP) {
Value *Sub24 = Builder.CreateAdd(
FloatWidth == 128 ? Call : Cast,
ConstantInt::getSigned(Builder.getIntNTy(BitWidthNew),
- -(BitWidth - FPMantissaWidth - 1)));
+ -(int)(BitWidth - FPMantissaWidth - 1)));
Value *ShProm25 = Builder.CreateZExt(Sub24, IntTy);
Value *Shl26 = Builder.CreateShl(IsSigned ? Sub : IntVal,
FloatWidth == 128 ? Sub24 : ShProm25);
@@ -853,7 +853,7 @@ static void expandIToFP(Instruction *IToFP) {
} else {
Value *Conv28 = Builder.CreateTrunc(Shr, Builder.getInt32Ty());
And29 = Builder.CreateAnd(
- Conv28, ConstantInt::getSigned(Builder.getInt32Ty(), 0x80000000));
+ Conv28, ConstantInt::get(Builder.getContext(), APInt::getSignMask(32)));
}
unsigned TempMod = FPMantissaWidth % 32;
Value *And34 = nullptr;
>From 17f283fdf98e3f33ea1e6eec5d52ceb16d44a098 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 14:51:18 +0100
Subject: [PATCH 6/9] [FastISel] Allow implicit trunc in FastISel for now
To reduce scope.
---
llvm/lib/CodeGen/SelectionDAG/FastISel.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 5c84059da273b..fa84f3615aacf 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1951,7 +1951,10 @@ Register FastISel::fastEmit_ri_(MVT VT, unsigned Opcode, Register Op0,
// fast-isel, which would be very slow.
IntegerType *ITy =
IntegerType::get(FuncInfo.Fn->getContext(), VT.getSizeInBits());
- MaterialReg = getRegForValue(ConstantInt::get(ITy, Imm));
+ // TODO: Avoid implicit trunc?
+ // See https://github.com/llvm/llvm-project/issues/112510.
+ MaterialReg = getRegForValue(
+ ConstantInt::get(ITy, Imm, /*IsSigned=*/false, /*ImplicitTrunc=*/true));
if (!MaterialReg)
return Register();
}
>From cd569104837288a5f356d1d343db3422d914bfee Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 15:08:30 +0100
Subject: [PATCH 7/9] [LSR] WRITE DESCRIPTION
---
llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 68cffd4c18688..10d6c73796b2a 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -3984,10 +3984,10 @@ void LSRInstance::GenerateReassociationsImpl(LSRUse &LU, unsigned LUIdx,
const SCEVConstant *InnerSumSC = dyn_cast<SCEVConstant>(InnerSum);
if (InnerSumSC && SE.getTypeSizeInBits(InnerSumSC->getType()) <= 64 &&
TTI.isLegalAddImmediate((uint64_t)F.UnfoldedOffset.getFixedValue() +
- InnerSumSC->getValue()->getZExtValue())) {
+ InnerSumSC->getValue()->getSExtValue())) {
F.UnfoldedOffset =
Immediate::getFixed((uint64_t)F.UnfoldedOffset.getFixedValue() +
- InnerSumSC->getValue()->getZExtValue());
+ InnerSumSC->getValue()->getSExtValue());
if (IsScaledReg) {
F.ScaledReg = nullptr;
F.Scale = 0;
@@ -4002,10 +4002,10 @@ void LSRInstance::GenerateReassociationsImpl(LSRUse &LU, unsigned LUIdx,
const SCEVConstant *SC = dyn_cast<SCEVConstant>(*J);
if (SC && SE.getTypeSizeInBits(SC->getType()) <= 64 &&
TTI.isLegalAddImmediate((uint64_t)F.UnfoldedOffset.getFixedValue() +
- SC->getValue()->getZExtValue()))
+ SC->getValue()->getSExtValue()))
F.UnfoldedOffset =
Immediate::getFixed((uint64_t)F.UnfoldedOffset.getFixedValue() +
- SC->getValue()->getZExtValue());
+ SC->getValue()->getSExtValue());
else
F.BaseRegs.push_back(*J);
// We may have changed the number of register in base regs, adjust the
>From 73871d07914d5c0b89a6d13234e9ea6ee8d4384e Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 15:11:05 +0100
Subject: [PATCH 8/9] [SLSR] Allow implicit truncation for element size
For now, we should implicitly truncate overflowing allocation
sizes when expanding GEPs, like we do in other places.
---
llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
index 2ad6f7e2e27cd..9591cd983df15 100644
--- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
@@ -1104,7 +1104,9 @@ void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
Value *ArrayIdx = GEP->getOperand(I);
uint64_t ElementSize = GTI.getSequentialElementStride(*DL);
IntegerType *PtrIdxTy = cast<IntegerType>(DL->getIndexType(GEP->getType()));
- ConstantInt *ElementSizeIdx = ConstantInt::get(PtrIdxTy, ElementSize, true);
+ // If the element size overflow the type, truncate.
+ ConstantInt *ElementSizeIdx =
+ ConstantInt::get(PtrIdxTy, ElementSize, true, /*ImplicitTrunc=*/true);
if (ArrayIdx->getType()->getIntegerBitWidth() <=
DL->getIndexSizeInBits(GEP->getAddressSpace())) {
// Skip factoring if ArrayIdx is wider than the index size, because
>From 0eb2003e87a3870fbf702532ab99148cfe0719f9 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Tue, 9 Dec 2025 15:29:51 +0100
Subject: [PATCH 9/9] [Hexagon] WIP
---
llvm/lib/Target/Hexagon/HexagonGenWideningVecInstr.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/Hexagon/HexagonGenWideningVecInstr.cpp b/llvm/lib/Target/Hexagon/HexagonGenWideningVecInstr.cpp
index 297410b3ad828..c15c2b4add778 100644
--- a/llvm/lib/Target/Hexagon/HexagonGenWideningVecInstr.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonGenWideningVecInstr.cpp
@@ -493,8 +493,7 @@ void HexagonGenWideningVecInstr::updateMPYConst(Intrinsic::ID IntId,
OP->getType()->isVectorTy()) {
// Create a vector with all elements equal to SplatVal
Type *VecTy = OP->getType();
- Value *splatVector =
- ConstantInt::get(VecTy, static_cast<uint32_t>(SplatVal));
+ Value *splatVector = ConstantInt::get(VecTy, SplatVal, !IsOPZExt);
OP = IsOPZExt ? IRB.CreateZExt(splatVector, VecTy)
: IRB.CreateSExt(splatVector, VecTy);
} else {
More information about the llvm-commits
mailing list