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
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-ir Author: None (elhewaty) ChangesThis patch adds the nuw (no unsigned wrap) and nsw (no signed wrap) 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:
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}
;.
|
Please fix test failures. |
There was a problem hiding this 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
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. |
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 llvm-project/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp Lines 46 to 75 in 12b802a
|
Failed Tests (8): |
@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? |
✅ With the latest revision this PR passed the C/C++ code formatter. |
I bisected a crash that I see when building the Linux kernel for arm64 to this change.
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
}
|
@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(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
}
There was a problem hiding this comment.
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
.
@elhewaty Looks like we have to check that --- 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: |
pullls in experimentally to try and fix asan hip build [IR] Fix crashes caused by llvm#85592 llvm#87169 Change-Id: Iee30a92a0e28b6949b69c34047fe2df9aabdd424
found a semantically important typo: #87285 |
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.
@elhewaty Would you like to add the support for dropping nsw/nuw flags in |
@dtcxzyw, I am thinking of filing a meta issue (task), and work on tasks related to this patch:
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? |
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. |
Following #85592, add support for nsw/nuw flags of trunc in SCCP.
We forgot to support these flags in |
And |
This patch fixes #85592 (comment). I found this while fixing flag propagation in my ["vectorizer"](https://github.com/dtcxzyw/llvm-codegen-benchmark/blob/main/vectorize.cpp).
This patch fixes llvm#85592 (comment). I found this while fixing flag propagation in my ["vectorizer"](https://github.com/dtcxzyw/llvm-codegen-benchmark/blob/main/vectorize.cpp).
Following llvm#85592, add support for nsw/nuw flags of trunc in SCCP.
This patch fixes llvm#85592 (comment). I found this while fixing flag propagation in my ["vectorizer"](https://github.com/dtcxzyw/llvm-codegen-benchmark/blob/main/vectorize.cpp).
@dtcxzyw are you working on this, too? |
llvm-project/llvm/lib/IR/Instruction.cpp Lines 678 to 683 in 84bc21f
Isn't it handled by this patch? |
I am sorry I missed this I read |
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