From ed3f06b9b393cd51e78e5fbc7a46bce090c1817a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 30 Oct 2023 09:04:04 +0100 Subject: [IR] Add zext nneg flag (#67982) Add an nneg flag to the zext instruction, which specifies that the argument is non-negative. Otherwise, the result is a poison value. The primary use-case for the flag is to preserve information when sext gets replaced with zext due to range-based canonicalization. The nneg flag allows us to convert the zext back into an sext later. This is useful for some optimizations (e.g. a signed icmp can fold with sext but not zext), as well as some targets (e.g. RISCV prefers sext over zext). Discourse thread: https://discourse.llvm.org/t/rfc-add-zext-nneg-flag/73914 This patch is based on https://reviews.llvm.org/D156444 by @Panagiotis156, with some implementation simplifications and additional tests. --------- Co-authored-by: Panagiotis K --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'llvm/lib/Bitcode/Writer/BitcodeWriter.cpp') diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index c427459..d7ebc76 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -123,6 +123,7 @@ enum { FUNCTION_INST_BINOP_ABBREV, FUNCTION_INST_BINOP_FLAGS_ABBREV, FUNCTION_INST_CAST_ABBREV, + FUNCTION_INST_CAST_FLAGS_ABBREV, FUNCTION_INST_RET_VOID_ABBREV, FUNCTION_INST_RET_VAL_ABBREV, FUNCTION_INST_UNREACHABLE_ABBREV, @@ -1551,6 +1552,9 @@ static uint64_t getOptimizationFlags(const Value *V) { Flags |= bitc::AllowContract; if (FPMO->hasApproxFunc()) Flags |= bitc::ApproxFunc; + } else if (const auto *NNI = dyn_cast(V)) { + if (NNI->hasNonNeg()) + Flags |= 1 << bitc::PNNI_NON_NEG; } return Flags; @@ -2827,6 +2831,12 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I, AbbrevToUse = FUNCTION_INST_CAST_ABBREV; Vals.push_back(VE.getTypeID(I.getType())); Vals.push_back(getEncodedCastOpcode(I.getOpcode())); + uint64_t Flags = getOptimizationFlags(&I); + if (Flags != 0) { + if (AbbrevToUse == FUNCTION_INST_CAST_ABBREV) + AbbrevToUse = FUNCTION_INST_CAST_FLAGS_ABBREV; + Vals.push_back(Flags); + } } else { assert(isa(I) && "Unknown instruction!"); Code = bitc::FUNC_CODE_INST_BINOP; @@ -3648,6 +3658,18 @@ void ModuleBitcodeWriter::writeBlockInfo() { FUNCTION_INST_CAST_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } + { // INST_CAST_FLAGS abbrev for FUNCTION_BLOCK. + auto Abbv = std::make_shared(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty + VE.computeBitsRequiredForTypeIndicies())); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // flags + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_CAST_FLAGS_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } { // INST_RET abbrev for FUNCTION_BLOCK. auto Abbv = std::make_shared(); -- cgit v1.1