llvm-project
llvm-project copied to clipboard
[IR] Add nowrap flags for trunc instruction
This patch adds the nuw (no unsigned wrap) and nsw (no signed wrap) poison-generating flags to the trunc instruction.
Discourse thread: https://discourse.llvm.org/t/rfc-add-nowrap-flags-to-trunc/77453
@llvm/pr-subscribers-llvm-transforms
@llvm/pr-subscribers-llvm-ir
Author: None (elhewaty)
Changes
This patch adds the nuw (no unsigned wrap) and nsw (no signed wrap) poison-generating flags to the trunc instruction.
Discourse thread: https://discourse.llvm.org/t/rfc-add-nowrap-flags-to-trunc/77453
Full diff: https://github.com/llvm/llvm-project/pull/85592.diff
12 Files Affected:
- (modified) llvm/docs/LangRef.rst (+10)
- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+7)
- (modified) llvm/include/llvm/IR/InstrTypes.h (+50)
- (modified) llvm/lib/AsmParser/LLParser.cpp (+13-1)
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+13-3)
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+5)
- (modified) llvm/lib/IR/AsmWriter.cpp (+5)
- (modified) llvm/lib/IR/Instruction.cpp (+30-4)
- (modified) llvm/lib/IR/Operator.cpp (+4)
- (modified) llvm/test/Assembler/flags.ll (+24)
- (modified) llvm/test/Bitcode/flags.ll (+8)
- (modified) llvm/test/Transforms/InstCombine/freeze.ll (+15-4)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 77ec72f176d6ed..902ba737bb1dd7 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -11295,6 +11295,9 @@ Syntax:
::
<result> = trunc <ty> <value> to <ty2> ; yields ty2
+ <result> = trunc nsw <ty> <value> to <ty2> ; yields ty2
+ <result> = trunc nuw <ty> <value> to <ty2> ; yields ty2
+ <result> = trunc nuw nsw <ty> <value> to <ty2> ; yields ty2
Overview:
"""""""""
@@ -11318,6 +11321,13 @@ and converts the remaining bits to ``ty2``. Since the source size must
be larger than the destination size, ``trunc`` cannot be a *no-op cast*.
It will always truncate bits.
+``nuw`` and ``nsw`` stand for "No Unsigned Wrap" and "No Signed Wrap",
+respectively. If the ``nuw`` and/or ``nsw`` keywords are present, the
+result value of the ``add`` is a :ref:`poison value <poisonvalues>` if
+any of the truncated bits are non-zero and/or any of the truncated bits
+are not the same as the top bit of the truncation result,respectively,
+occurs.
+
Example:
""""""""
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index c0a52d64a101d0..5e776c940e197e 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -491,6 +491,13 @@ enum OverflowingBinaryOperatorOptionalFlags {
OBO_NO_SIGNED_WRAP = 1
};
+/// PossiblyNoWrapInstOptionalFlags - Flags for serializing
+/// PossiblyNoWrapInstOptionalFlags's SubclassOptionalData contents.
+enum PossiblyNoWrapInstOptionalFlags {
+ PNWIO_NO_UNSIGNED_WRAP = 0,
+ PNWIO_NO_SIGNED_WRAP = 1
+};
+
/// FastMath Flags
/// This is a fixed layout derived from the bitcode emitted by LLVM 5.0
/// intended to decouple the in-memory representation from the serialization.
diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index fed21b992e3d10..dd7b253f2f0d93 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -946,6 +946,56 @@ class PossiblyNonNegInst : public CastInst {
}
};
+/// Cast Instruction that can have a nowrap flags (only trunc)
+class PossiblyNoWrapInst : public CastInst {
+public:
+ enum { AnyWrap = 0, NoUnsignedWrap = (1 << 0), NoSignedWrap = (1 << 1) };
+
+ static bool classof(const Instruction *I) {
+ return I->getOpcode() == Instruction::Trunc;
+ }
+
+ static bool classof(const Value *V) {
+ return isa<Instruction>(V) && classof(cast<Instruction>(V));
+ }
+
+ void setHasNoUnsignedWrap(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap);
+ }
+ void setHasNoSignedWrap(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap);
+ }
+
+ /// Transparently provide more efficient getOperand methods.
+ DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+
+ /// Test whether this operation is known to never
+ /// undergo unsigned overflow, aka the nuw property.
+ bool hasNoUnsignedWrap() const {
+ return SubclassOptionalData & NoUnsignedWrap;
+ }
+
+ /// Test whether this operation is known to never
+ /// undergo signed overflow, aka the nsw property.
+ bool hasNoSignedWrap() const {
+ return (SubclassOptionalData & NoSignedWrap) != 0;
+ }
+
+ /// Returns the no-wrap kind of the operation.
+ unsigned getNoWrapKind() const {
+ unsigned NoWrapKind = 0;
+ if (hasNoUnsignedWrap())
+ NoWrapKind |= NoUnsignedWrap;
+
+ if (hasNoSignedWrap())
+ NoWrapKind |= NoSignedWrap;
+
+ return NoWrapKind;
+ }
+};
+
//===----------------------------------------------------------------------===//
// CmpInst Class
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 2e0f5ba82220c9..83c0121265139d 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -6772,7 +6772,19 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB,
Inst->setNonNeg();
return 0;
}
- case lltok::kw_trunc:
+ case lltok::kw_trunc: {
+ bool NUW = EatIfPresent(lltok::kw_nuw);
+ bool NSW = EatIfPresent(lltok::kw_nsw);
+ if (!NUW)
+ NUW = EatIfPresent(lltok::kw_nuw);
+ if (parseCast(Inst, PFS, KeywordVal))
+ return true;
+ if (NUW)
+ cast<PossiblyNoWrapInst>(Inst)->setHasNoUnsignedWrap(true);
+ if (NSW)
+ cast<PossiblyNoWrapInst>(Inst)->setHasNoSignedWrap(true);
+ return false;
+ }
case lltok::kw_sext:
case lltok::kw_fptrunc:
case lltok::kw_fpext:
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 9c63116114f3c5..a1a493b201a3b1 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -4995,9 +4995,19 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
return error("Invalid cast");
I = CastInst::Create(CastOp, Op, ResTy);
}
- if (OpNum < Record.size() && isa<PossiblyNonNegInst>(I) &&
- (Record[OpNum] & (1 << bitc::PNNI_NON_NEG)))
- I->setNonNeg(true);
+
+ if (OpNum < Record.size()) {
+ if (Opc == Instruction::ZExt) {
+ if (Record[OpNum] & (1 << bitc::PNNI_NON_NEG))
+ cast<PossiblyNonNegInst>(I)->setNonNeg(true);
+ } else if (Opc == Instruction::Trunc) {
+ if (Record[OpNum] & (1 << bitc::PNWIO_NO_UNSIGNED_WRAP))
+ cast<PossiblyNoWrapInst>(I)->setHasNoUnsignedWrap(true);
+ if (Record[OpNum] & (1 << bitc::PNWIO_NO_SIGNED_WRAP))
+ cast<PossiblyNoWrapInst>(I)->setHasNoSignedWrap(true);
+ }
+ }
+
InstructionList.push_back(I);
break;
}
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 597f49332fad25..e0ddf123254ddc 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1636,6 +1636,11 @@ static uint64_t getOptimizationFlags(const Value *V) {
} else if (const auto *NNI = dyn_cast<PossiblyNonNegInst>(V)) {
if (NNI->hasNonNeg())
Flags |= 1 << bitc::PNNI_NON_NEG;
+ } else if (const auto *PNWI = dyn_cast<PossiblyNoWrapInst>(V)) {
+ if (PNWI->hasNoSignedWrap())
+ Flags |= 1 << bitc::PNWIO_NO_SIGNED_WRAP;
+ if (PNWI->hasNoUnsignedWrap())
+ Flags |= 1 << bitc::PNWIO_NO_UNSIGNED_WRAP;
}
return Flags;
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 1beb4c069a6997..546b2ffdaa5256 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1411,6 +1411,11 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
} else if (const auto *NNI = dyn_cast<PossiblyNonNegInst>(U)) {
if (NNI->hasNonNeg())
Out << " nneg";
+ } else if (const auto *PNWI = dyn_cast<PossiblyNoWrapInst>(U)) {
+ if (PNWI->hasNoUnsignedWrap())
+ Out << " nuw";
+ if (PNWI->hasNoSignedWrap())
+ Out << " nsw";
}
}
diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index e0892398f43445..1c8dca7e40f0c7 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -368,11 +368,19 @@ bool Instruction::isOnlyUserOfAnyOperand() {
}
void Instruction::setHasNoUnsignedWrap(bool b) {
- cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(b);
+ if (auto Inst = cast<OverflowingBinaryOperator>(this)) {
+ Inst->setHasNoUnsignedWrap(b);
+ } else {
+ cast<PossiblyNoWrapInst>(this)->setHasNoUnsignedWrap(b);
+ }
}
void Instruction::setHasNoSignedWrap(bool b) {
- cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(b);
+ if (auto Inst = cast<OverflowingBinaryOperator>(this)) {
+ Inst->setHasNoSignedWrap(b);
+ } else {
+ cast<PossiblyNoWrapInst>(this)->setHasNoSignedWrap(b);
+ }
}
void Instruction::setIsExact(bool b) {
@@ -386,11 +394,17 @@ void Instruction::setNonNeg(bool b) {
}
bool Instruction::hasNoUnsignedWrap() const {
- return cast<OverflowingBinaryOperator>(this)->hasNoUnsignedWrap();
+ if (auto Inst = cast<OverflowingBinaryOperator>(this))
+ return Inst->hasNoUnsignedWrap();
+
+ return cast<PossiblyNoWrapInst>(this)->hasNoUnsignedWrap();
}
bool Instruction::hasNoSignedWrap() const {
- return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap();
+ if (auto Inst = cast<OverflowingBinaryOperator>(this))
+ return Inst->hasNoSignedWrap();
+
+ return cast<PossiblyNoWrapInst>(this)->hasNoSignedWrap();
}
bool Instruction::hasNonNeg() const {
@@ -430,6 +444,11 @@ void Instruction::dropPoisonGeneratingFlags() {
case Instruction::ZExt:
setNonNeg(false);
break;
+
+ case Instruction::Trunc:
+ cast<PossiblyNoWrapInst>(this)->setHasNoUnsignedWrap(false);
+ cast<PossiblyNoWrapInst>(this)->setHasNoSignedWrap(false);
+ break;
}
if (isa<FPMathOperator>(this)) {
@@ -624,6 +643,13 @@ void Instruction::andIRFlags(const Value *V) {
}
}
+ if (auto *PNWI = dyn_cast<PossiblyNoWrapInst>(V)) {
+ if (isa<PossiblyNoWrapInst>(this)) {
+ setHasNoSignedWrap(hasNoSignedWrap() && PNWI->hasNoSignedWrap());
+ setHasNoUnsignedWrap(hasNoUnsignedWrap() && PNWI->hasNoUnsignedWrap());
+ }
+ }
+
if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
if (isa<PossiblyExactOperator>(this))
setIsExact(isExact() && PE->isExact());
diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp
index caf8fe654a36dc..ec292316d1265f 100644
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -27,6 +27,10 @@ bool Operator::hasPoisonGeneratingFlags() const {
auto *OBO = cast<OverflowingBinaryOperator>(this);
return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap();
}
+ case Instruction::Trunc: {
+ auto *PNWI = dyn_cast<PossiblyNoWrapInst>(this);
+ return PNWI->hasNoUnsignedWrap() || PNWI->hasNoSignedWrap();
+ }
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::AShr:
diff --git a/llvm/test/Assembler/flags.ll b/llvm/test/Assembler/flags.ll
index 04bddd02f50c81..aef2aeba7c78a6 100644
--- a/llvm/test/Assembler/flags.ll
+++ b/llvm/test/Assembler/flags.ll
@@ -261,3 +261,27 @@ define i64 @test_or(i64 %a, i64 %b) {
%res = or disjoint i64 %a, %b
ret i64 %res
}
+
+define i32 @test_trunc_signed(i64 %a) {
+; CHECK: %res = trunc nsw i64 %a to i32
+ %res = trunc nsw i64 %a to i32
+ ret i32 %res
+}
+
+define i32 @test_trunc_unsigned(i64 %a) {
+; CHECK: %res = trunc nuw i64 %a to i32
+ %res = trunc nuw i64 %a to i32
+ ret i32 %res
+}
+
+define i32 @test_trunc_both(i64 %a) {
+; CHECK: %res = trunc nuw nsw i64 %a to i32
+ %res = trunc nuw nsw i64 %a to i32
+ ret i32 %res
+}
+
+define i32 @test_trunc_both_reversed(i64 %a) {
+; CHECK: %res = trunc nuw nsw i64 %a to i32
+ %res = trunc nsw nuw i64 %a to i32
+ ret i32 %res
+}
diff --git a/llvm/test/Bitcode/flags.ll b/llvm/test/Bitcode/flags.ll
index e3fc827d865d7e..2eee96f3356424 100644
--- a/llvm/test/Bitcode/flags.ll
+++ b/llvm/test/Bitcode/flags.ll
@@ -20,6 +20,10 @@ second: ; preds = %first
%ll = zext i32 %s to i64
%jj = or disjoint i32 %a, 0
%oo = or i32 %a, 0
+ %tu = trunc nuw i32 %a to i16
+ %ts = trunc nsw i32 %a to i16
+ %tus = trunc nuw nsw i32 %a to i16
+ %t = trunc i32 %a to i16
unreachable
first: ; preds = %entry
@@ -32,5 +36,9 @@ first: ; preds = %entry
%rr = zext i32 %ss to i64
%mm = or disjoint i32 %a, 0
%nn = or i32 %a, 0
+ %tuu = trunc nuw i32 %a to i16
+ %tss = trunc nsw i32 %a to i16
+ %tuss = trunc nuw nsw i32 %a to i16
+ %tt = trunc i32 %a to i16
br label %second
}
diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll
index da59101d5710cb..e8105b6287d0c5 100644
--- a/llvm/test/Transforms/InstCombine/freeze.ll
+++ b/llvm/test/Transforms/InstCombine/freeze.ll
@@ -1049,7 +1049,7 @@ exit:
define ptr @freeze_load_noundef(ptr %ptr) {
; CHECK-LABEL: @freeze_load_noundef(
-; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !noundef !0
+; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !noundef [[META0:![0-9]+]]
; CHECK-NEXT: ret ptr [[P]]
;
%p = load ptr, ptr %ptr, !noundef !0
@@ -1059,7 +1059,7 @@ define ptr @freeze_load_noundef(ptr %ptr) {
define ptr @freeze_load_dereferenceable(ptr %ptr) {
; CHECK-LABEL: @freeze_load_dereferenceable(
-; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable !1
+; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable [[META1:![0-9]+]]
; CHECK-NEXT: ret ptr [[P]]
;
%p = load ptr, ptr %ptr, !dereferenceable !1
@@ -1138,6 +1138,17 @@ define i32 @propagate_drop_flags_or(i32 %arg) {
ret i32 %v1.fr
}
+define i32 @propagate_drop_flags_trunc(i64 %arg) {
+; CHECK-LABEL: @propagate_drop_flags_trunc(
+; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i64 [[ARG:%.*]]
+; CHECK-NEXT: [[V1:%.*]] = trunc i64 [[ARG_FR]] to i32
+; CHECK-NEXT: ret i32 [[V1]]
+;
+ %v1 = trunc nsw nuw i64 %arg to i32
+ %v1.fr = freeze i32 %v1
+ ret i32 %v1.fr
+}
+
!0 = !{}
!1 = !{i64 4}
!2 = !{i32 0, i32 100}
@@ -1145,8 +1156,8 @@ define i32 @propagate_drop_flags_or(i32 %arg) {
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
; CHECK: attributes #[[ATTR1]] = { nounwind }
;.
-; CHECK: [[META0:![0-9]+]] = !{}
-; CHECK: [[META1:![0-9]+]] = !{i64 4}
+; CHECK: [[META0]] = !{}
+; CHECK: [[META1]] = !{i64 4}
; CHECK: [[RNG2]] = !{i32 0, i32 100}
; CHECK: [[RNG3]] = !{i32 0, i32 33}
;.
@nikic, @jayfoad, @preames, @topperc @dtcxzyw @arsenm @goldsteinn @RKSimon please review. It causes some regressions, but I shared it to get some ideas.
Failed Tests (8): LLVM :: CodeGen/Hexagon/packed-store.ll LLVM :: Transforms/GVN/callbr-scalarpre-critedge.ll LLVM :: Transforms/GVN/invariant.group.ll LLVM :: Transforms/GVN/pre-new-inst.ll LLVM :: Transforms/GVNHoist/hoist-pr20242.ll LLVM :: Transforms/GVNSink/sink-common-code.ll LLVM :: Transforms/PhaseOrdering/X86/vec-load-combine.ll LLVM :: Transforms/SimplifyCFG/dont-hoist-deoptimize.ll
Please fix test failures.
One more place you need to update for correctness reasons is InstCombineSimplifyDemanded: You need to drop poison generating flags when doing demanded bits simplification of trunc now. (This should be tested.)
Another place to update is SCEVExpander, which backs up poison-generating flags. Needs an adjustment to handle these on trunc now. (Don't think this needs a test, it's pretty tricky to do that.)
Please also add a test in llvm/test/Transforms/SimplifyCFG/HoistCode.ll for the flag intersection behavior. See existing disjoint/nneg tests.
Another place to update is SCEVExpander, which backs up poison-generating flags. Needs an adjustment to handle these on trunc now. (Don't think this needs a test, it's pretty tricky to do that.)
before modifying the SCEVExpander, are these places legal to modify here, should we add a class like this, should we modift this to
Another place to update is SCEVExpander, which backs up poison-generating flags. Needs an adjustment to handle these on trunc now. (Don't think this needs a test, it's pretty tricky to do that.)
before modifying the SCEVExpander, are these places legal to modify here, should we add a class like this, should we modift this to
You should not modify any of those places (at least in this PR), only https://github.com/llvm/llvm-project/blob/12b802ac0bc6ddf0742aa3fe8caecd8204d70ca5/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp#L46-L75
Failed Tests (8): LLVM :: CodeGen/Hexagon/packed-store.ll LLVM :: Transforms/GVN/callbr-scalarpre-critedge.ll LLVM :: Transforms/GVN/invariant.group.ll LLVM :: Transforms/GVN/pre-new-inst.ll LLVM :: Transforms/GVNHoist/hoist-pr20242.ll LLVM :: Transforms/GVNSink/sink-common-code.ll LLVM :: Transforms/PhaseOrdering/X86/vec-load-combine.ll LLVM :: Transforms/SimplifyCFG/dont-hoist-deoptimize.ll
@dtcxzyw can you please take a look at the review questions I posted?
@dtcxzyw can you please take a look at the review questions I posted?
It seems all questions have been answered by other reviewers. Did you forget to submit your pending comments?
:white_check_mark: With the latest revision this PR passed the C/C++ code formatter.
:white_check_mark: With the latest revision this PR passed the Python code formatter.
@RKSimon, If you plan to propagate this down to SDAG I want to work on it, if possible. Can you share similar work as a reference?
@nikic is there any follow-up work depending on this?
@elhewaty There is a lot of possible followup work here, I think some of the most important piece would be:
- Implement inference for nuw/nsw flags in InstCombine
- Implement zext(trunc nuw) and sext(trunc nsw) fold
- Emit trunc nuw/nsw in SimplifyIndVars IV widening
And beyond that switching various transform to make use of the flags, for example this fold should use the flags instead of checking KnownBits: https://github.com/llvm/llvm-project/blob/3a2c70b3713a856ea416d92abdddb7893fca308b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L1504
@elhewaty I've started playing with some vector test coverage already - once this has landed I'll commit the tests, raise a ticket and assign it to you.
@nikic, Thanks, I will work on them all.
@elhewaty I've started playing with some vector test coverage already - once this has landed I'll commit the tests, raise a ticket and assign it to you.
Thanks, I am looking forward to it.
@elhewaty There is a lot of possible followup work here, I think some of the most important piece would be:
- Implement inference for nuw/nsw flags in InstCombine
- Implement zext(trunc nuw) and sext(trunc nsw) fold
- Emit trunc nuw/nsw in SimplifyIndVars IV widening
@nikic, I'm taking a look at point 3. Not super familiar w/ IV widening, but I guess whenever the uses are truncated, we want to preserve the information that previously got lost? I'm mainly referring to widenIVUse/truncateIVUse and variants thereof (e.g., widenWithVariantUse) (cc/ @dtcxzyw).
@antoniofrighetto
@nikic, I'm taking a look at point 3. Not super familiar w/ IV widening, but I guess whenever the uses are truncated, we want to preserve the information that previously got lost? I'm mainly referring to
widenIVUse/truncateIVUseand variants thereof (e.g.,widenWithVariantUse) (cc/ @dtcxzyw).
I am taking a look too, I am not familiar with w/ IV widening, So I think it's a good chance for me to work on it. I will look at the functions you mentioned too. Thanks
@dtcxzyw, @nikic ping :bell: !
I bisected a crash that I see when building the Linux kernel for arm64 to this change.
# bad: [a4de589d117a4fd52554da3c61ae6eb26c90a0c8] [InstallAPI] Add support for parsing dSYMs (#86852)
# good: [552c8eb731a1fabef4d81e2a69911506adf39e22] [SLP][NFC]Add a test with the wrong result extension after reduction, NFC.
git bisect start 'a4de589d117a4fd52554da3c61ae6eb26c90a0c8' '552c8eb731a1fabef4d81e2a69911506adf39e22'
# good: [39fe729502006f1b108828b75af8d63a27364f80] [lld-macho] Ignore -no_warn_duplicate_libraries flag (#86303)
git bisect good 39fe729502006f1b108828b75af8d63a27364f80
# good: [219511aee21cc652e1ede0458de4a4a66f04c81c] [APINotes] Make an assert in a std::sort call tolerate self-comparisons
git bisect good 219511aee21cc652e1ede0458de4a4a66f04c81c
# bad: [28760b63bbf9e267713957105a8d17091fb0d20e] Revert "Reapply "[clang][nullability] allow _Nonnull etc on nullable class types (#82705)"" (#87041)
git bisect bad 28760b63bbf9e267713957105a8d17091fb0d20e
# good: [01e02e0b6a15562e241e9ed18b295c66ae20f410] [SLP]Fix PR87011: Do not assume that initial ext/trunc nodes can be represented by bitwidth without analysis.
git bisect good 01e02e0b6a15562e241e9ed18b295c66ae20f410
# good: [e005a09df5b5c7d210ac7cd8cbddb3a4a8663173] [RISCV][TypePromotion] Dont generate truncs if PromotedType is greater than Source Type (#86941)
git bisect good e005a09df5b5c7d210ac7cd8cbddb3a4a8663173
# bad: [235d6841601a9dbea293b8e82b0c994f91f42d76] [C++20] [Modules] [Reduced BMI] Don't record declarations in functions by default
git bisect bad 235d6841601a9dbea293b8e82b0c994f91f42d76
# bad: [7d3924cee30a87a51f9dc04ec843ae6bc3d1c90e] [IR] Add nowrap flags for trunc instruction (#85592)
git bisect bad 7d3924cee30a87a51f9dc04ec843ae6bc3d1c90e
# good: [ba6b2d22af177a72b132cdb8e9350a708f282d2c] [LLDB] Add APFloat helper functions to Scalar class. (#86862)
git bisect good ba6b2d22af177a72b132cdb8e9350a708f282d2c
# first bad commit: [7d3924cee30a87a51f9dc04ec843ae6bc3d1c90e] [IR] Add nowrap flags for trunc instruction (#85592)
A trivial C and LLVM IR reproducer:
int __kmalloc_index(long size) {
if (size <= 4)
return 1;
if (size <= 4 * 4)
return 2;
asm("");
__builtin_unreachable();
}
void kmalloc_trace(int *);
void *kmalloc(long size) {
int index = __kmalloc_index(size);
kmalloc_trace(&index);
return 0;
}
int unittest_data_add() {
extern unsigned char __dtbo_testcases_begin[], __dtbo_testcases_end[];
int size = __dtbo_testcases_end - __dtbo_testcases_begin;
void *ret = kmalloc(size + 8);
if (ret)
;
return 0;
}
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
@__dtbo_testcases_begin = external global [0 x i8]
define i32 @__kmalloc_index(i64 %size) {
entry:
%cmp = icmp slt i64 %size, 0
br i1 %cmp, label %return, label %if.end
if.end: ; preds = %entry
%cmp1 = icmp eq i64 %size, 0
br i1 %cmp1, label %return, label %if.end3
if.end3: ; preds = %if.end
store volatile i32 0, ptr null, align 4294967296
unreachable
return: ; preds = %if.end, %entry
%retval.0 = phi i32 [ 1, %entry ], [ 0, %if.end ]
ret i32 %retval.0
}
define ptr @kmalloc(i64 %size, ptr %index) {
entry:
%call = call i32 @__kmalloc_index(i64 %size)
store i32 %call, ptr %index, align 4
ret ptr null
}
define i32 @unittest_data_add() {
entry:
%add = add i32 trunc (i64 sub (i64 0, i64 ptrtoint (ptr @__dtbo_testcases_begin to i64)) to i32), 1
%conv = sext i32 %add to i64
%call1 = call ptr @kmalloc(i64 %conv, ptr null)
ret i32 0
}
$ clang -O2 -c -o /dev/null unittest.i
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments: clang -O2 -c -o /dev/null unittest.i
1. <eof> parser at end of file
2. Optimizer
#0 0x0000555c136a5e06 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4087e06)
#1 0x0000555c136a387e llvm::sys::RunSignalHandlers() (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x408587e)
#2 0x0000555c1361e6ed CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#3 0x00007f3fbb0f0770 (/usr/lib/libc.so.6+0x3c770)
#4 0x0000555c131e1727 llvm::Operator::hasPoisonGeneratingFlags() const (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3bc3727)
#5 0x0000555c131e18e9 llvm::Operator::hasPoisonGeneratingFlagsOrMetadata() const (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3bc38e9)
#6 0x0000555c12a7335f canCreateUndefOrPoison(llvm::Operator const*, UndefPoisonKind, bool) ValueTracking.cpp:0:0
#7 0x0000555c12a73bca isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
#8 0x0000555c12a8f0b5 llvm::Use const* std::__find_if_not<llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>>(llvm::Use const*, llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>) ValueTracking.cpp:0:0
#9 0x0000555c12a73d77 isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
#10 0x0000555c12a8f0b5 llvm::Use const* std::__find_if_not<llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>>(llvm::Use const*, llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>) ValueTracking.cpp:0:0
#11 0x0000555c12a73d77 isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
#12 0x0000555c12a737b7 impliesPoison(llvm::Value const*, llvm::Value const*, unsigned int) ValueTracking.cpp:0:0
#13 0x0000555c137cbfb1 createLogicalOp(llvm::IRBuilderBase&, llvm::Instruction::BinaryOps, llvm::Value*, llvm::Value*, llvm::Twine const&) SimplifyCFG.cpp:0:0
#14 0x0000555c137da5cb (anonymous namespace)::SimplifyCFGOpt::simplifyCondBranch(llvm::BranchInst*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&) SimplifyCFG.cpp:0:0
#15 0x0000555c137c6805 (anonymous namespace)::SimplifyCFGOpt::run(llvm::BasicBlock*) SimplifyCFG.cpp:0:0
#16 0x0000555c137c3923 llvm::simplifyCFG(llvm::BasicBlock*, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&, llvm::ArrayRef<llvm::WeakVH>) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x41a5923)
#17 0x0000555c135b996d iterativelySimplifyCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#18 0x0000555c135b9373 simplifyFunctionCFGImpl(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#19 0x0000555c135b803f simplifyFunctionCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#20 0x0000555c135b7df6 llvm::SimplifyCFGPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3f99df6)
#21 0x0000555c13ecb9ad llvm::detail::PassModel<llvm::Function, llvm::SimplifyCFGPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) BackendUtil.cpp:0:0
#22 0x0000555c131e65e6 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3bc85e6)
#23 0x0000555c1277464d llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) X86CodeGenPassBuilder.cpp:0:0
#24 0x0000555c132858a1 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3c678a1)
#25 0x0000555c14b2246d llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::CGSCCToFunctionPassAdaptor, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) PassBuilder.cpp:0:0
#26 0x0000555c132805ce llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3c625ce)
#27 0x0000555c14b08b5d llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) PassBuilder.cpp:0:0
#28 0x0000555c13283aed llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3c65aed)
#29 0x0000555c14b232dd llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::DevirtSCCRepeatedPass, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) PassBuilder.cpp:0:0
#30 0x0000555c1328250d llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3c6450d)
#31 0x0000555c14b08e0d llvm::detail::PassModel<llvm::Module, llvm::ModuleToPostOrderCGSCCPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) PassBuilder.cpp:0:0
#32 0x0000555c131e5826 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3bc7826)
#33 0x0000555c14c285ef llvm::ModuleInlinerWrapperPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x560a5ef)
#34 0x0000555c14b0fa3d llvm::detail::PassModel<llvm::Module, llvm::ModuleInlinerWrapperPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) PassBuilder.cpp:0:0
#35 0x0000555c131e5826 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x3bc7826)
#36 0x0000555c13ec1967 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#37 0x0000555c13eb7c20 clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4899c20)
#38 0x0000555c13edda31 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x48bfa31)
#39 0x0000555c152f57a9 clang::ParseAST(clang::Sema&, bool, bool) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x5cd77a9)
#40 0x0000555c14351a5d clang::FrontendAction::Execute() (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4d33a5d)
#41 0x0000555c142b949d clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4c9b49d)
#42 0x0000555c1442cc54 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4e0ec54)
#43 0x0000555c11eb9af0 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x289baf0)
#44 0x0000555c11eb63be ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#45 0x0000555c140eb429 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::$_0>(long) Job.cpp:0:0
#46 0x0000555c1361e426 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4000426)
#47 0x0000555c140eaab3 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4accab3)
#48 0x0000555c140a153c clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4a8353c)
#49 0x0000555c140a1a97 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4a83a97)
#50 0x0000555c140c3819 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x4aa5819)
#51 0x0000555c11eb58ad clang_main(int, char**, llvm::ToolContext const&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x28978ad)
#52 0x0000555c11ec6b76 main (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x28a8b76)
#53 0x00007f3fbb0d9cd0 (/usr/lib/libc.so.6+0x25cd0)
#54 0x00007f3fbb0d9d8a __libc_start_main (/usr/lib/libc.so.6+0x25d8a)
#55 0x0000555c11eb3ca5 _start (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/clang-19+0x2895ca5)
clang: error: clang frontend command failed with exit code 139 (use -v to see invocation)
ClangBuiltLinux clang version 19.0.0git (https://github.com/llvm/llvm-project.git 7d3924cee30a87a51f9dc04ec843ae6bc3d1c90e)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin
clang: note: diagnostic msg: Error generating preprocessed source(s) - no preprocessable inputs.
$ opt -O2 -disable-output reduced.ll
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: opt -O2 -disable-output reduced.ll
#0 0x000055f4ac43a636 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x1e31636)
#1 0x000055f4ac437f9e llvm::sys::RunSignalHandlers() (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x1e2ef9e)
#2 0x000055f4ac43b074 SignalHandler(int) Signals.cpp:0:0
#3 0x00007f7a8edde770 (/usr/lib/libc.so.6+0x3c770)
#4 0x000055f4ac5e93e7 llvm::Operator::hasPoisonGeneratingFlags() const (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x1fe03e7)
#5 0x000055f4ac5e95a9 llvm::Operator::hasPoisonGeneratingFlagsOrMetadata() const (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x1fe05a9)
#6 0x000055f4ac768d2f canCreateUndefOrPoison(llvm::Operator const*, UndefPoisonKind, bool) ValueTracking.cpp:0:0
#7 0x000055f4ac76959a isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
#8 0x000055f4ac7867d5 llvm::Use const* std::__find_if_not<llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>>(llvm::Use const*, llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>) ValueTracking.cpp:0:0
#9 0x000055f4ac769747 isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
#10 0x000055f4ac7867d5 llvm::Use const* std::__find_if_not<llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>>(llvm::Use const*, llvm::Use const*, __gnu_cxx::__ops::_Iter_pred<isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind)::$_0>) ValueTracking.cpp:0:0
#11 0x000055f4ac769747 isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
#12 0x000055f4ac769187 impliesPoison(llvm::Value const*, llvm::Value const*, unsigned int) ValueTracking.cpp:0:0
#13 0x000055f4acae4931 createLogicalOp(llvm::IRBuilderBase&, llvm::Instruction::BinaryOps, llvm::Value*, llvm::Value*, llvm::Twine const&) SimplifyCFG.cpp:0:0
#14 0x000055f4acaf307b (anonymous namespace)::SimplifyCFGOpt::simplifyCondBranch(llvm::BranchInst*, llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>&) SimplifyCFG.cpp:0:0
#15 0x000055f4acaded85 (anonymous namespace)::SimplifyCFGOpt::run(llvm::BasicBlock*) SimplifyCFG.cpp:0:0
#16 0x000055f4acadbea3 llvm::simplifyCFG(llvm::BasicBlock*, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&, llvm::ArrayRef<llvm::WeakVH>) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x24d2ea3)
#17 0x000055f4ad4731fd iterativelySimplifyCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#18 0x000055f4ad472c03 simplifyFunctionCFGImpl(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#19 0x000055f4ad47180f simplifyFunctionCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#20 0x000055f4ad4715c6 llvm::SimplifyCFGPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x2e685c6)
#21 0x000055f4adf2082d llvm::detail::PassModel<llvm::Function, llvm::SimplifyCFGPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#22 0x000055f4ac632d16 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x2029d16)
#23 0x000055f4ada9781d llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) X86CodeGenPassBuilder.cpp:0:0
#24 0x000055f4adce5651 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x36dc651)
#25 0x000055f4adf2664d llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::CGSCCToFunctionPassAdaptor, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) PassBuilderPipelines.cpp:0:0
#26 0x000055f4adce037e llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x36d737e)
#27 0x000055f4adf3303d llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) PassBuilderPipelines.cpp:0:0
#28 0x000055f4adce389d llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x36da89d)
#29 0x000055f4adf58a1d llvm::detail::PassModel<llvm::LazyCallGraph::SCC, llvm::DevirtSCCRepeatedPass, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) Inliner.cpp:0:0
#30 0x000055f4adce22bd llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x36d92bd)
#31 0x000055f4adf290bd llvm::detail::PassModel<llvm::Module, llvm::ModuleToPostOrderCGSCCPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) PassBuilderPipelines.cpp:0:0
#32 0x000055f4ac6317f6 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x20287f6)
#33 0x000055f4adf5577f llvm::ModuleInlinerWrapperPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x394c77f)
#34 0x000055f4adf26a7d llvm::detail::PassModel<llvm::Module, llvm::ModuleInlinerWrapperPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) PassBuilderPipelines.cpp:0:0
#35 0x000055f4ac6317f6 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x20287f6)
#36 0x000055f4adeb5914 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x38ac914)
#37 0x000055f4ac3ffa45 optMain (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x1df6a45)
#38 0x00007f7a8edc7cd0 (/usr/lib/libc.so.6+0x25cd0)
#39 0x00007f7a8edc7d8a __libc_start_main (/usr/lib/libc.so.6+0x25d8a)
#40 0x000055f4ac3f92e5 _start (/home/nathan/tmp/cvise.RCofO58saD/install/llvm-bad/bin/opt+0x1df02e5)
I bisected a crash that I see when building the Linux kernel for arm64 to this change.
@dtcxzyw, Any idea about what may cause this?
@elhewaty Looks like we have to check that dyn_cast is actually applicable, as we may be dealing with ConstantExpr, not just Instruction (which is the case in the above function that leads to the crash), e.g.:
--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -28,8 +28,9 @@ bool Operator::hasPoisonGeneratingFlags() const {
return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap();
}
case Instruction::Trunc: {
- auto *TI = dyn_cast<TruncInst>(this);
- return TI->hasNoUnsignedWrap() || TI->hasNoSignedWrap();
+ if (auto *TI = dyn_cast<TruncInst>(this))
+ return TI->hasNoUnsignedWrap() || TI->hasNoSignedWrap();
+ return false;
}
case Instruction::UDiv:
case Instruction::SDiv:
found a semantically important typo: https://github.com/llvm/llvm-project/pull/87285
@elhewaty Would you like to add the support for dropping nsw/nuw flags in llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp:reduceFlagsInModule?
@dtcxzyw, I am thinking of filing a meta issue (task), and work on tasks related to this patch:
- [x] Add nowrap flags
- [x] Fix unexpected crashes
- [ ] Lower the nowrap flags to SDAG
- [x] Add the support for dropping nsw/nuw flags to
llvm-reduce - [x] Infer nsw/nuw flags in instCombine
- [ ] Implement zext(trunc nuw) and sext(trunc nsw) fold
- [ ] Emit trunc nuw/nsw in SimplifyIndVars IV widening
- [ ] Look for opportunities in the code to use trunc nuw/nsw
but I am busy these days, I will continue working on these tasks, but if you need them, and they are urgent you can work on them.
what do you think?
- [ ] Add the support for dropping nsw/nuw flags to
llvm-reduce
I've already implemented this but haven't had working internet to push it
I would like to add the support for the flags in SCCP.
We forgot to support these flags in Instruction::copyIRFlags :(
I will post a patch later.