From db02fce95e89b5dc6a1b86989d6e92a7fa8e2e39 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 25 Apr 2025 14:29:37 -0700 Subject: [PATCH 1/2] [TableGen][SelectionDAG][GISel] Support IsNonExtLoad for IsAtomic PatFrags. Use it for RISC-V as a demonstration. Other targets will follow. --- .../include/llvm/Target/TargetSelectionDAG.td | 32 ++++++++++++++++ llvm/lib/Target/RISCV/RISCVInstrInfoA.td | 4 +- llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td | 8 ++-- .../TableGen/Common/CodeGenDAGPatterns.cpp | 37 ++++++++++--------- llvm/utils/TableGen/GlobalISelEmitter.cpp | 21 ++++++----- 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td index e5ffcceeba8a7..a53527442719a 100644 --- a/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -1835,6 +1835,13 @@ defm atomic_load_uinc_wrap : binary_atomic_op; defm atomic_load_udec_wrap : binary_atomic_op; defm atomic_cmp_swap : ternary_atomic_op; +/// Atomic load which does not extend. +def atomic_load_nonext : + PatFrag<(ops node:$ptr), (atomic_load node:$ptr)> { + let IsAtomic = true; // FIXME: Should be IsLoad and/or IsAtomic? + let IsNonExtLoad = true; +} + /// Atomic load which zeroes the excess high bits. def atomic_load_zext : PatFrag<(ops node:$ptr), (atomic_load node:$ptr)> { @@ -1876,6 +1883,7 @@ def atomic_load_32 : let IsAtomic = true; let MemoryVT = i32; } + def atomic_load_64 : PatFrag<(ops node:$ptr), (atomic_load node:$ptr)> { @@ -1883,6 +1891,30 @@ def atomic_load_64 : let MemoryVT = i64; } +def atomic_load_nonext_8 : + PatFrag<(ops node:$ptr), (atomic_load_nonext node:$ptr)> { + let IsAtomic = true; // FIXME: Should be IsLoad and/or IsAtomic? + let MemoryVT = i8; +} + +def atomic_load_nonext_16 : + PatFrag<(ops node:$ptr), (atomic_load_nonext node:$ptr)> { + let IsAtomic = true; // FIXME: Should be IsLoad and/or IsAtomic? + let MemoryVT = i16; +} + +def atomic_load_nonext_32 : + PatFrag<(ops node:$ptr), (atomic_load_nonext node:$ptr)> { + let IsAtomic = true; // FIXME: Should be IsLoad and/or IsAtomic? + let MemoryVT = i32; +} + +def atomic_load_nonext_64 : + PatFrag<(ops node:$ptr), (atomic_load_nonext node:$ptr)> { + let IsAtomic = true; // FIXME: Should be IsLoad and/or IsAtomic? + let MemoryVT = i64; +} + def atomic_load_zext_8 : PatFrag<(ops node:$ptr), (atomic_load_zext node:$ptr)> { let IsAtomic = true; // FIXME: Should be IsLoad and/or IsAtomic? diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td index b348e774d50b8..74873a66bc8c9 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -174,12 +174,12 @@ let Predicates = [HasAtomicLdSt] in { } let Predicates = [HasAtomicLdSt, IsRV32] in { - def : LdPat, LW>; + def : LdPat, LW>; } let Predicates = [HasAtomicLdSt, IsRV64] in { def : LdPat, LW>; - def : LdPat, LD, i64>; + def : LdPat, LD, i64>; def : StPat, SD, GPR, i64>; } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td index 837aa7f1005af..5e013b496c6b1 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZalasr.td @@ -95,8 +95,8 @@ let Predicates = [HasStdExtZalasr] in { } // Predicates = [HasStdExtZalasr] let Predicates = [HasStdExtZalasr, IsRV32] in { - def : PatLAQ, LW_AQ>; - def : PatLAQ, LW_AQ>; + def : PatLAQ, LW_AQ>; + def : PatLAQ, LW_AQ>; } // Predicates = [HasStdExtZalasr, IsRV64] @@ -104,8 +104,8 @@ let Predicates = [HasStdExtZalasr, IsRV64] in { def : PatLAQ, LW_AQ>; def : PatLAQ, LW_AQ>; - def : PatLAQ, LD_AQ>; - def : PatLAQ, LD_AQ>; + def : PatLAQ, LD_AQ>; + def : PatLAQ, LD_AQ>; def : PatSRL, SD_RL>; def : PatSRL, SD_RL>; diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp index a4fa063ae61cb..b2bc3c335b661 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp @@ -933,21 +933,19 @@ std::string TreePredicateFn::getPredCode() const { getMinAlignment() < 1) PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), "IsLoad cannot be used by itself"); - } else { + } else if (!isAtomic()) { if (isNonExtLoad()) PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), - "IsNonExtLoad requires IsLoad"); - if (!isAtomic()) { - if (isAnyExtLoad()) - PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), - "IsAnyExtLoad requires IsLoad or IsAtomic"); - if (isSignExtLoad()) - PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), - "IsSignExtLoad requires IsLoad or IsAtomic"); - if (isZeroExtLoad()) - PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), - "IsZeroExtLoad requires IsLoad or IsAtomic"); - } + "IsNonExtLoad requires IsLoad or IsAtomic"); + if (isAnyExtLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsAnyExtLoad requires IsLoad or IsAtomic"); + if (isSignExtLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsSignExtLoad requires IsLoad or IsAtomic"); + if (isZeroExtLoad()) + PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), + "IsZeroExtLoad requires IsLoad or IsAtomic"); } if (isStore()) { @@ -966,10 +964,10 @@ std::string TreePredicateFn::getPredCode() const { } if (isAtomic()) { - if (getMemoryVT() == nullptr && !isAtomicOrderingMonotonic() && - getAddressSpaces() == nullptr && + if (getMemoryVT() == nullptr && getAddressSpaces() == nullptr && // FIXME: Should atomic loads be IsLoad, IsAtomic, or both? - !isAnyExtLoad() && !isZeroExtLoad() && !isSignExtLoad() && + !isNonExtLoad() && !isAnyExtLoad() && !isZeroExtLoad() && !isSignExtLoad() && + !isAtomicOrderingMonotonic() && !isAtomicOrderingAcquire() && !isAtomicOrderingRelease() && !isAtomicOrderingAcquireRelease() && !isAtomicOrderingSequentiallyConsistent() && @@ -1076,11 +1074,14 @@ std::string TreePredicateFn::getPredCode() const { "return false;\n"; if (isAtomic()) { - if ((isAnyExtLoad() + isSignExtLoad() + isZeroExtLoad()) > 1) + if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + isZeroExtLoad()) > 1) PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), - "IsAnyExtLoad, IsSignExtLoad, and IsZeroExtLoad are " + "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and IsZeroExtLoad are " "mutually exclusive"); + if (isNonExtLoad()) + Code += "if (cast(N)->getExtensionType() != " + "ISD::NON_EXTLOAD) return false;\n"; if (isAnyExtLoad()) Code += "if (cast(N)->getExtensionType() != ISD::EXTLOAD) " "return false;\n"; diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index b3bad55ebf278..b9561c137ec8b 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -622,16 +622,17 @@ Expected GlobalISelEmitter::addBuiltinPredicates( } // G_LOAD is used for both non-extending and any-extending loads. - if (Predicate.isLoad() && Predicate.isNonExtLoad()) { - InsnMatcher.addPredicate( - 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0); - return InsnMatcher; - } - if ((Predicate.isLoad() || Predicate.isAtomic()) && - Predicate.isAnyExtLoad()) { - InsnMatcher.addPredicate( - 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0); - return InsnMatcher; + if (Predicate.isLoad() || Predicate.isAtomic()) { + if (Predicate.isNonExtLoad()) { + InsnMatcher.addPredicate( + 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0); + return InsnMatcher; + } + if (Predicate.isAnyExtLoad()) { + InsnMatcher.addPredicate( + 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0); + return InsnMatcher; + } } if (Predicate.isStore()) { From 1882bf1a4238f4cc6396bdc2227fc7204f1038b5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 25 Apr 2025 14:31:09 -0700 Subject: [PATCH 2/2] fixup! clang-format --- llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp index b2bc3c335b661..615c077fe4bdc 100644 --- a/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp @@ -966,8 +966,8 @@ std::string TreePredicateFn::getPredCode() const { if (isAtomic()) { if (getMemoryVT() == nullptr && getAddressSpaces() == nullptr && // FIXME: Should atomic loads be IsLoad, IsAtomic, or both? - !isNonExtLoad() && !isAnyExtLoad() && !isZeroExtLoad() && !isSignExtLoad() && - !isAtomicOrderingMonotonic() && + !isNonExtLoad() && !isAnyExtLoad() && !isZeroExtLoad() && + !isSignExtLoad() && !isAtomicOrderingMonotonic() && !isAtomicOrderingAcquire() && !isAtomicOrderingRelease() && !isAtomicOrderingAcquireRelease() && !isAtomicOrderingSequentiallyConsistent() && @@ -1074,10 +1074,12 @@ std::string TreePredicateFn::getPredCode() const { "return false;\n"; if (isAtomic()) { - if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + isZeroExtLoad()) > 1) - PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(), - "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and IsZeroExtLoad are " - "mutually exclusive"); + if ((isNonExtLoad() + isAnyExtLoad() + isSignExtLoad() + isZeroExtLoad()) > + 1) + PrintFatalError( + getOrigPatFragRecord()->getRecord()->getLoc(), + "IsNonExtLoad, IsAnyExtLoad, IsSignExtLoad, and IsZeroExtLoad are " + "mutually exclusive"); if (isNonExtLoad()) Code += "if (cast(N)->getExtensionType() != "