Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IR] Add nowrap flags for trunc instruction #85592

Merged
merged 3 commits into from Mar 29, 2024
Merged

Conversation

elhewaty
Copy link
Contributor

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

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 18, 2024

@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}
 ;.

@elhewaty
Copy link
Contributor Author

elhewaty commented Mar 18, 2024

@nikic, @jayfoad, @preames, @topperc @dtcxzyw @arsenm @goldsteinn @RKSimon please review.
It causes some regressions, but I shared it to get some ideas.

llvm/docs/LangRef.rst Outdated Show resolved Hide resolved
llvm/docs/LangRef.rst Outdated Show resolved Hide resolved
llvm/lib/IR/Instruction.cpp Outdated Show resolved Hide resolved
@dtcxzyw
Copy link
Member

dtcxzyw commented Mar 18, 2024

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.

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow up should add support to llvm-reduce to strip these

llvm/include/llvm/IR/InstrTypes.h Outdated Show resolved Hide resolved
llvm/lib/IR/Instruction.cpp Outdated Show resolved Hide resolved
llvm/docs/LangRef.rst Outdated Show resolved Hide resolved
@nikic
Copy link
Contributor

nikic commented Mar 18, 2024

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.)

llvm/test/Assembler/flags.ll Outdated Show resolved Hide resolved
@nikic
Copy link
Contributor

nikic commented Mar 18, 2024

Please also add a test in llvm/test/Transforms/SimplifyCFG/HoistCode.ll for the flag intersection behavior. See existing disjoint/nneg tests.

@elhewaty
Copy link
Contributor Author

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

@nikic
Copy link
Contributor

nikic commented Mar 18, 2024

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

PoisonFlags::PoisonFlags(const Instruction *I) {
NUW = false;
NSW = false;
Exact = false;
Disjoint = false;
NNeg = false;
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(I)) {
NUW = OBO->hasNoUnsignedWrap();
NSW = OBO->hasNoSignedWrap();
}
if (auto *PEO = dyn_cast<PossiblyExactOperator>(I))
Exact = PEO->isExact();
if (auto *PDI = dyn_cast<PossiblyDisjointInst>(I))
Disjoint = PDI->isDisjoint();
if (auto *PNI = dyn_cast<PossiblyNonNegInst>(I))
NNeg = PNI->hasNonNeg();
}
void PoisonFlags::apply(Instruction *I) {
if (isa<OverflowingBinaryOperator>(I)) {
I->setHasNoUnsignedWrap(NUW);
I->setHasNoSignedWrap(NSW);
}
if (isa<PossiblyExactOperator>(I))
I->setIsExact(Exact);
if (auto *PDI = dyn_cast<PossiblyDisjointInst>(I))
PDI->setIsDisjoint(Disjoint);
if (auto *PNI = dyn_cast<PossiblyNonNegInst>(I))
PNI->setNonNeg(NNeg);
}

@dtcxzyw
Copy link
Member

dtcxzyw commented Mar 22, 2024


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

@elhewaty
Copy link
Contributor Author

@dtcxzyw can you please take a look at the review questions I posted?

@dtcxzyw
Copy link
Member

dtcxzyw commented Mar 22, 2024

@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?

llvm/lib/IR/Instruction.cpp Outdated Show resolved Hide resolved
llvm/lib/IR/Instruction.cpp Outdated Show resolved Hide resolved
llvm/lib/IR/Instruction.cpp Outdated Show resolved Hide resolved
Copy link

github-actions bot commented Mar 22, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@nathanchance
Copy link
Member

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)

@elhewaty
Copy link
Contributor Author

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?

@@ -27,6 +27,10 @@ bool Operator::hasPoisonGeneratingFlags() const {
auto *OBO = cast<OverflowingBinaryOperator>(this);
return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap();
}
case Instruction::Trunc: {
auto *TI = dyn_cast<TruncInst>(this);
return TI->hasNoUnsignedWrap() || TI->hasNoSignedWrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TI may be null because this may be a CastConstantExpr.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dtcxzyw I will open another pull and fix this.

Copy link
Contributor Author

@elhewaty elhewaty Mar 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you think of a small test for this?

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) ; I tried to replace this with call i32 @use(i64 %conv) and remove all the other functions, but It works fine 
  ret i32 0
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@g_var = external global [0 x i8]

define i64 @test_ret_noundef_add_constantexpr() {
entry:
  %add = add i32 trunc (i64 sub (i64 0, i64 ptrtoint (ptr @g_var to i64)) to i32), 1
  %conv = sext i32 %add to i64
  ret i64 %conv
}

Think you can put it in test/Transforms/FunctionAttrs/noundef.ll.

@antoniofrighetto
Copy link
Contributor

@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:

searlmc1 pushed a commit to ROCm/llvm-project that referenced this pull request Mar 31, 2024
pullls in experimentally to try and fix asan hip build
[IR] Fix crashes caused by llvm#85592 llvm#87169

Change-Id: Iee30a92a0e28b6949b69c34047fe2df9aabdd424
@programmerjake
Copy link
Contributor

found a semantically important typo: #87285

dtcxzyw pushed a commit that referenced this pull request Apr 2, 2024
This patch fixes the crash caused by the pull request:
#85592
RKSimon added a commit that referenced this pull request Apr 3, 2024
Based off #85592 - our truncation -> PACKSS/PACKUS folds should be able to use the nsw/nuw flags to recognise when we don't need to mask/sext_inreg prior to the PACKSS/PACKUS nodes.
@dtcxzyw
Copy link
Member

dtcxzyw commented Apr 4, 2024

@elhewaty Would you like to add the support for dropping nsw/nuw flags in llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp:reduceFlagsInModule?

@elhewaty
Copy link
Contributor Author

elhewaty commented Apr 5, 2024

@dtcxzyw, I am thinking of filing a meta issue (task), and work on tasks related to this patch:

  • Add nowrap flags
  • Fix unexpected crashes
  • Lower the nowrap flags to SDAG
  • Add the support for dropping nsw/nuw flags to llvm-reduce
  • 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?

@arsenm
Copy link
Contributor

arsenm commented Apr 6, 2024

  • 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

@XChy
Copy link
Member

XChy commented Apr 7, 2024

I would like to add the support for the flags in SCCP.

XChy added a commit that referenced this pull request Apr 11, 2024
Following #85592, add support for nsw/nuw flags of trunc in SCCP.
@dtcxzyw
Copy link
Member

dtcxzyw commented Apr 19, 2024

We forgot to support these flags in Instruction::copyIRFlags :(
I will post a patch later.

@elhewaty
Copy link
Contributor Author

We forgot to support these flags in Instruction::copyIRFlags :( I will post a patch later.

And Instruction::andIRFlags too :(

dtcxzyw added a commit that referenced this pull request Apr 19, 2024
aniplcc pushed a commit to aniplcc/llvm-project that referenced this pull request Apr 21, 2024
tmatheson-arm pushed a commit to tmatheson-arm/llvm-project that referenced this pull request Apr 22, 2024
Following llvm#85592, add support for nsw/nuw flags of trunc in SCCP.
tmatheson-arm pushed a commit to tmatheson-arm/llvm-project that referenced this pull request Apr 22, 2024
@elhewaty
Copy link
Contributor Author

We forgot to support these flags in Instruction::copyIRFlags :( I will post a patch later.

And Instruction::andIRFlags too :(

@dtcxzyw are you working on this, too?

@dtcxzyw
Copy link
Member

dtcxzyw commented Apr 24, 2024

We forgot to support these flags in Instruction::copyIRFlags :( I will post a patch later.

And Instruction::andIRFlags too :(

@dtcxzyw are you working on this, too?

if (auto *TI = dyn_cast<TruncInst>(V)) {
if (isa<TruncInst>(this)) {
setHasNoSignedWrap(hasNoSignedWrap() && TI->hasNoSignedWrap());
setHasNoUnsignedWrap(hasNoUnsignedWrap() && TI->hasNoUnsignedWrap());
}
}

Isn't it handled by this patch?

@elhewaty
Copy link
Contributor Author

I am sorry I missed this I read copyIRflags as andIRflags.
I should have double-checked this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet