[llvm] a809862 - [IR] Teach `drop/hasPoisonGeneratingAnnotations()` about `abs`, `ctlz` and `cttz` (#175941)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 14 16:02:02 PST 2026
Author: Nathan Corbyn
Date: 2026-01-15T00:01:58Z
New Revision: a8098629bce2decd4b52aebaf179cbc480603dd2
URL: https://github.com/llvm/llvm-project/commit/a8098629bce2decd4b52aebaf179cbc480603dd2
DIFF: https://github.com/llvm/llvm-project/commit/a8098629bce2decd4b52aebaf179cbc480603dd2.diff
LOG: [IR] Teach `drop/hasPoisonGeneratingAnnotations()` about `abs`, `ctlz` and `cttz` (#175941)
Added:
Modified:
llvm/lib/Analysis/ValueTracking.cpp
llvm/lib/IR/Instruction.cpp
llvm/lib/IR/Operator.cpp
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
llvm/test/Transforms/InstCombine/freeze-integer-intrinsics.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ece8425aef698..171952120fc40 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7573,9 +7573,8 @@ static bool canCreateUndefOrPoison(const Operator *Op, UndefPoisonKind Kind,
case Intrinsic::ctlz:
case Intrinsic::cttz:
case Intrinsic::abs:
- if (cast<ConstantInt>(II->getArgOperand(1))->isNullValue())
- return false;
- break;
+ // We're not considering flags so it is safe to just return false.
+ return false;
case Intrinsic::sshl_sat:
case Intrinsic::ushl_sat:
if (!includesPoison(Kind) ||
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 7682c28e23b33..3c35c656dca84 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -473,6 +473,19 @@ void Instruction::dropPoisonGeneratingFlags() {
case Instruction::ICmp:
cast<ICmpInst>(this)->setSameSign(false);
break;
+
+ case Instruction::Call: {
+ if (auto *II = dyn_cast<IntrinsicInst>(this)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::ctlz:
+ case Intrinsic::cttz:
+ case Intrinsic::abs:
+ II->setOperand(1, ConstantInt::getFalse(getContext()));
+ break;
+ }
+ }
+ break;
+ }
}
if (isa<FPMathOperator>(this)) {
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index c3e54a0fc0c7e..bd92a32142ebc 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -14,6 +14,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "ConstantsContext.h"
@@ -53,6 +54,16 @@ bool Operator::hasPoisonGeneratingFlags() const {
return false;
case Instruction::ICmp:
return cast<ICmpInst>(this)->hasSameSign();
+ case Instruction::Call:
+ if (auto *II = dyn_cast<IntrinsicInst>(this)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::ctlz:
+ case Intrinsic::cttz:
+ case Intrinsic::abs:
+ return cast<ConstantInt>(II->getArgOperand(1))->isOneValue();
+ }
+ }
+ [[fallthrough]];
default:
if (const auto *FP = dyn_cast<FPMathOperator>(this))
return FP->hasNoNaNs() || FP->hasNoInfs();
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 1f415ffa8eed2..d4604e05de688 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1396,9 +1396,6 @@ static Value *foldSelectCttzCtlz(ICmpInst *ICI, Value *TrueVal, Value *FalseVal,
// sizeof in bits of 'Count'.
unsigned SizeOfInBits = Count->getType()->getScalarSizeInBits();
if (match(ValueOnZero, m_SpecificInt(SizeOfInBits))) {
- // Explicitly clear the 'is_zero_poison' flag. It's always valid to go from
- // true to false on this flag, so we can replace it for all users.
- II->setArgOperand(1, ConstantInt::getFalse(II->getContext()));
// A range annotation on the intrinsic may no longer be valid.
II->dropPoisonGeneratingAnnotations();
IC.addToWorklist(II);
@@ -3885,8 +3882,6 @@ static Instruction *foldBitCeil(SelectInst &SI, IRBuilderBase &Builder,
// Drop range attributes and re-infer them in the next iteration.
cast<Instruction>(Ctlz)->dropPoisonGeneratingAnnotations();
- // Set is_zero_poison to false and re-infer them in the next iteration.
- cast<Instruction>(Ctlz)->setOperand(1, Builder.getFalse());
IC.addToWorklist(cast<Instruction>(Ctlz));
Value *Neg = Builder.CreateNeg(Ctlz);
Value *Masked =
diff --git a/llvm/test/Transforms/InstCombine/freeze-integer-intrinsics.ll b/llvm/test/Transforms/InstCombine/freeze-integer-intrinsics.ll
index 3cab09c2876bf..fa464d80f3d2b 100644
--- a/llvm/test/Transforms/InstCombine/freeze-integer-intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/freeze-integer-intrinsics.ll
@@ -3,9 +3,9 @@
define i32 @ctlz_true_freeze(i32 %arg) {
; CHECK-LABEL: @ctlz_true_freeze(
-; CHECK-NEXT: [[CALL:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[ARG:%.*]], i1 true)
-; CHECK-NEXT: [[FREEZE:%.*]] = freeze i32 [[CALL]]
-; CHECK-NEXT: ret i32 [[FREEZE]]
+; CHECK-NEXT: [[FREEZE:%.*]] = freeze i32 [[CALL:%.*]]
+; CHECK-NEXT: [[CALL1:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[FREEZE]], i1 false)
+; CHECK-NEXT: ret i32 [[CALL1]]
;
%call = call i32 @llvm.ctlz.i32(i32 %arg, i1 true)
%freeze = freeze i32 %call
@@ -35,9 +35,9 @@ define i32 @ctlz_true_noundef_freeze(i32 %arg) {
define i32 @cttz_true_freeze(i32 %arg) {
; CHECK-LABEL: @cttz_true_freeze(
-; CHECK-NEXT: [[CALL:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[ARG:%.*]], i1 true)
-; CHECK-NEXT: [[FREEZE:%.*]] = freeze i32 [[CALL]]
-; CHECK-NEXT: ret i32 [[FREEZE]]
+; CHECK-NEXT: [[FREEZE:%.*]] = freeze i32 [[CALL:%.*]]
+; CHECK-NEXT: [[CALL1:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[FREEZE]], i1 false)
+; CHECK-NEXT: ret i32 [[CALL1]]
;
%call = call i32 @llvm.cttz.i32(i32 %arg, i1 true)
%freeze = freeze i32 %call
@@ -89,9 +89,9 @@ define i32 @freeze_cttz_false(i32 %arg) {
define i32 @abs_true_i32(i32 %arg) {
; CHECK-LABEL: @abs_true_i32(
-; CHECK-NEXT: [[CALL:%.*]] = call i32 @llvm.abs.i32(i32 [[ARG:%.*]], i1 true)
-; CHECK-NEXT: [[FREEZE:%.*]] = freeze i32 [[CALL]]
-; CHECK-NEXT: ret i32 [[FREEZE]]
+; CHECK-NEXT: [[FREEZE:%.*]] = freeze i32 [[CALL:%.*]]
+; CHECK-NEXT: [[CALL1:%.*]] = call i32 @llvm.abs.i32(i32 [[FREEZE]], i1 false)
+; CHECK-NEXT: ret i32 [[CALL1]]
;
%call = call i32 @llvm.abs.i32(i32 %arg, i1 true)
%freeze = freeze i32 %call
More information about the llvm-commits
mailing list