Skip to content

Commit

Permalink
[CodeGen] Add nneg and disjoint flags (llvm#86650)
Browse files Browse the repository at this point in the history
MachineInstr learned the new flags.
  • Loading branch information
tschuett authored Mar 26, 2024
1 parent d0e97fe commit da6cc4a
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 2 deletions.
2 changes: 2 additions & 0 deletions llvm/include/llvm/CodeGen/MachineInstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class MachineInstr
// this instruction.
Unpredictable = 1 << 16, // Instruction with unpredictable condition.
NoConvergent = 1 << 17, // Call does not require convergence guarantees.
NonNeg = 1 << 18, // The operand is non-negative.
Disjoint = 1 << 19, // Each bit is zero in at least one of the inputs.
};

private:
Expand Down
7 changes: 6 additions & 1 deletion llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1562,9 +1562,14 @@ bool IRTranslator::translateCast(unsigned Opcode, const User &U,
if (U.getType()->getScalarType()->isBFloatTy() ||
U.getOperand(0)->getType()->getScalarType()->isBFloatTy())
return false;

uint32_t Flags = 0;
if (const Instruction *I = dyn_cast<Instruction>(&U))
Flags = MachineInstr::copyFlagsFromInstruction(*I);

Register Op = getOrCreateVReg(*U.getOperand(0));
Register Res = getOrCreateVReg(U);
MIRBuilder.buildInstr(Opcode, {Res}, {Op});
MIRBuilder.buildInstr(Opcode, {Res}, {Op}, Flags);
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/MIRParser/MILexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
.Case("nuw", MIToken::kw_nuw)
.Case("nsw", MIToken::kw_nsw)
.Case("exact", MIToken::kw_exact)
.Case("nneg", MIToken::kw_nneg)
.Case("disjoint", MIToken::kw_disjoint)
.Case("nofpexcept", MIToken::kw_nofpexcept)
.Case("unpredictable", MIToken::kw_unpredictable)
.Case("debug-location", MIToken::kw_debug_location)
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/CodeGen/MIRParser/MILexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ struct MIToken {
kw_exact,
kw_nofpexcept,
kw_unpredictable,
kw_nneg,
kw_disjoint,
kw_debug_location,
kw_debug_instr_number,
kw_dbg_instr_ref,
Expand Down
8 changes: 7 additions & 1 deletion llvm/lib/CodeGen/MIRParser/MIParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1471,7 +1471,9 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
Token.is(MIToken::kw_exact) ||
Token.is(MIToken::kw_nofpexcept) ||
Token.is(MIToken::kw_noconvergent) ||
Token.is(MIToken::kw_unpredictable)) {
Token.is(MIToken::kw_unpredictable) ||
Token.is(MIToken::kw_nneg) ||
Token.is(MIToken::kw_disjoint)) {
// clang-format on
// Mine frame and fast math flags
if (Token.is(MIToken::kw_frame_setup))
Expand Down Expand Up @@ -1504,6 +1506,10 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) {
Flags |= MachineInstr::Unpredictable;
if (Token.is(MIToken::kw_noconvergent))
Flags |= MachineInstr::NoConvergent;
if (Token.is(MIToken::kw_nneg))
Flags |= MachineInstr::NonNeg;
if (Token.is(MIToken::kw_disjoint))
Flags |= MachineInstr::Disjoint;

lex();
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/CodeGen/MIRPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,10 @@ void MIPrinter::print(const MachineInstr &MI) {
OS << "unpredictable ";
if (MI.getFlag(MachineInstr::NoConvergent))
OS << "noconvergent ";
if (MI.getFlag(MachineInstr::NonNeg))
OS << "nneg ";
if (MI.getFlag(MachineInstr::Disjoint))
OS << "disjoint ";

OS << TII->getName(MI.getOpcode());
if (I < E)
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/CodeGen/MachineInstr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,17 @@ uint32_t MachineInstr::copyFlagsFromInstruction(const Instruction &I) {
MIFlags |= MachineInstr::MIFlag::NoUWrap;
}

// Copy the nonneg flag.
if (const PossiblyNonNegInst *PNI = dyn_cast<PossiblyNonNegInst>(&I)) {
if (PNI->hasNonNeg())
MIFlags |= MachineInstr::MIFlag::NonNeg;
// Copy the disjoint flag.
} else if (const PossiblyDisjointInst *PD =
dyn_cast<PossiblyDisjointInst>(&I)) {
if (PD->isDisjoint())
MIFlags |= MachineInstr::MIFlag::Disjoint;
}

// Copy the exact flag.
if (const PossiblyExactOperator *PE = dyn_cast<PossiblyExactOperator>(&I))
if (PE->isExact())
Expand Down Expand Up @@ -1706,6 +1717,10 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
OS << "nofpexcept ";
if (getFlag(MachineInstr::NoMerge))
OS << "nomerge ";
if (getFlag(MachineInstr::NonNeg))
OS << "nneg ";
if (getFlag(MachineInstr::Disjoint))
OS << "disjoint ";

// Print the opcode name.
if (TII)
Expand Down
135 changes: 135 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-nneg-disjoint.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
; RUN: llc -mtriple=aarch64-linux-gnu -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s

define i32 @call_nneg(i16 %a) {
; CHECK-LABEL: name: call_nneg
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: %2:_(s32) = nneg G_ZEXT [[TRUNC]](s16)
; CHECK-NEXT: $w0 = COPY %2(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
entry:
%result = zext nneg i16 %a to i32
ret i32 %result
}

define i32 @call_not_nneg(i16 %a) {
; CHECK-LABEL: name: call_not_nneg
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16)
; CHECK-NEXT: $w0 = COPY [[ZEXT]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
entry:
%result = zext i16 %a to i32
ret i32 %result
}

define i32 @call_disjoint(i32 %a, i32 %b) {
; CHECK-LABEL: name: call_disjoint
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: %2:_(s32) = disjoint G_OR [[COPY]], [[COPY1]]
; CHECK-NEXT: $w0 = COPY %2(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
entry:
%result = or disjoint i32 %a, %b
ret i32 %result
}

define i32 @call_add(i32 %a, i32 %b) {
; CHECK-LABEL: name: call_add
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = nsw G_ADD [[COPY]], [[COPY1]]
; CHECK-NEXT: $w0 = COPY [[ADD]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
entry:
%result = add nsw i32 %a, %b
ret i32 %result
}

define i32 @call_not_disjoint(i32 %a, i32 %b) {
; CHECK-LABEL: name: call_not_disjoint
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[COPY]], [[COPY1]]
; CHECK-NEXT: $w0 = COPY [[OR]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
entry:
%result = or i32 %a, %b
ret i32 %result
}

define <2 x i64> @call_not_disjoint_vector(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: name: call_not_disjoint_vector
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $q0, $q1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
; CHECK-NEXT: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[COPY]], [[COPY1]]
; CHECK-NEXT: $q0 = COPY [[OR]](<2 x s64>)
; CHECK-NEXT: RET_ReallyLR implicit $q0
entry:
%result = or <2 x i64> %a, %b
ret <2 x i64> %result
}

define <2 x i64> @call_disjoint_vector(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: name: call_disjoint_vector
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $q0, $q1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1
; CHECK-NEXT: %2:_(<2 x s64>) = disjoint G_OR [[COPY]], [[COPY1]]
; CHECK-NEXT: $q0 = COPY %2(<2 x s64>)
; CHECK-NEXT: RET_ReallyLR implicit $q0
entry:
%result = or disjoint <2 x i64> %a, %b
ret <2 x i64> %result
}

define <2 x i64> @call_nneg_vector(<2 x i32> %a) {
; CHECK-LABEL: name: call_nneg_vector
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $d0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
; CHECK-NEXT: %1:_(<2 x s64>) = nneg G_ZEXT [[COPY]](<2 x s32>)
; CHECK-NEXT: $q0 = COPY %1(<2 x s64>)
; CHECK-NEXT: RET_ReallyLR implicit $q0
entry:
%result = zext nneg <2 x i32> %a to <2 x i64>
ret <2 x i64> %result
}

define <2 x i64> @call_not_nneg_vector(<2 x i32> %a) {
; CHECK-LABEL: name: call_not_nneg_vector
; CHECK: bb.1.entry:
; CHECK-NEXT: liveins: $d0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x s64>) = G_ZEXT [[COPY]](<2 x s32>)
; CHECK-NEXT: $q0 = COPY [[ZEXT]](<2 x s64>)
; CHECK-NEXT: RET_ReallyLR implicit $q0
entry:
%result = zext <2 x i32> %a to <2 x i64>
ret <2 x i64> %result
}

0 comments on commit da6cc4a

Please sign in to comment.