diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h @@ -94,6 +94,13 @@ bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override; + + std::pair + decomposeMachineOperandsTargetFlags(unsigned TF) const override; + + ArrayRef> + getSerializableDirectMachineOperandTargetFlags() const override; + protected: const RISCVSubtarget &STI; }; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -597,3 +597,28 @@ } return false; } + +std::pair +RISCVInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { + const unsigned Mask = RISCVII::MO_DIRECT_FLAG_MASK; + return std::make_pair(TF & Mask, TF & ~Mask); +} + +ArrayRef> +RISCVInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { + using namespace RISCVII; + static const std::pair TargetFlags[] = { + {MO_CALL, "riscv-call"}, + {MO_PLT, "riscv-plt"}, + {MO_LO, "riscv-lo"}, + {MO_HI, "riscv-hi"}, + {MO_PCREL_LO, "riscv-pcrel-lo"}, + {MO_PCREL_HI, "riscv-pcrel-hi"}, + {MO_GOT_HI, "riscv-got-hi"}, + {MO_TPREL_LO, "riscv-tprel-lo"}, + {MO_TPREL_HI, "riscv-tprel-hi"}, + {MO_TPREL_ADD, "riscv-tprel-add"}, + {MO_TLS_GOT_HI, "riscv-tls-got-hi"}, + {MO_TLS_GD_HI, "riscv-tls-gd-hi"}}; + return makeArrayRef(TargetFlags); +} diff --git a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h --- a/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -48,20 +48,26 @@ InstFormatMask = 31 }; +// RISC-V Specific Machine Operand Flags enum { - MO_None, - MO_CALL, - MO_PLT, - MO_LO, - MO_HI, - MO_PCREL_LO, - MO_PCREL_HI, - MO_GOT_HI, - MO_TPREL_LO, - MO_TPREL_HI, - MO_TPREL_ADD, - MO_TLS_GOT_HI, - MO_TLS_GD_HI, + MO_None = 0, + MO_CALL = 1, + MO_PLT = 2, + MO_LO = 3, + MO_HI = 4, + MO_PCREL_LO = 5, + MO_PCREL_HI = 6, + MO_GOT_HI = 7, + MO_TPREL_LO = 8, + MO_TPREL_HI = 9, + MO_TPREL_ADD = 10, + MO_TLS_GOT_HI = 11, + MO_TLS_GD_HI = 12, + + // Used to differentiate between target-specific "direct" flags and "bitmask" + // flags. A machine operand can only have one "direct" flag, but can have + // multiple "bitmask" flags. + MO_DIRECT_FLAG_MASK = 15 }; } // namespace RISCVII diff --git a/llvm/test/CodeGen/RISCV/mir-target-flags.ll b/llvm/test/CodeGen/RISCV/mir-target-flags.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/mir-target-flags.ll @@ -0,0 +1,78 @@ +; RUN: llc -mtriple=riscv32 --code-model=small \ +; RUN: -stop-after riscv-expand-pseudo %s -o %t.mir +; RUN: llc -mtriple=riscv32 -run-pass none %t.mir -o - | \ +; RUN: FileCheck %s -check-prefix=RV32-SMALL +; +; RUN: llc -mtriple=riscv32 --code-model=medium --relocation-model=pic \ +; RUN: -stop-after riscv-expand-pseudo %s -o %t.mir +; RUN: llc -mtriple=riscv32 -run-pass none %t.mir -o - | \ +; RUN: FileCheck %s -check-prefix=RV32-MED + +; This tests the RISC-V-specific serialization and deserialization of +; `target-flags(...)` + +@g_e = external global i32 +@g_i = internal global i32 0 +@t_un = external thread_local global i32 +@t_ld = external thread_local(localdynamic) global i32 +@t_ie = external thread_local(initialexec) global i32 +@t_le = external thread_local(localexec) global i32 + +declare i32 @callee(i32) nounwind + +define i32 @caller(i32 %a) nounwind { +; RV32-SMALL-LABEL: name: caller +; RV32-SMALL: target-flags(riscv-hi) @g_e +; RV32-SMALL-NEXT: target-flags(riscv-lo) @g_e +; RV32-SMALL-NEXT: target-flags(riscv-hi) @g_i +; RV32-SMALL-NEXT: target-flags(riscv-lo) @g_i +; RV32-SMALL-NEXT: target-flags(riscv-tprel-hi) @t_un +; RV32-SMALL-NEXT: target-flags(riscv-tprel-add) @t_un +; RV32-SMALL-NEXT: target-flags(riscv-tprel-lo) @t_un +; RV32-SMALL-NEXT: target-flags(riscv-tprel-hi) @t_ld +; RV32-SMALL-NEXT: target-flags(riscv-tprel-add) @t_ld +; RV32-SMALL-NEXT: target-flags(riscv-tprel-lo) @t_ld +; RV32-SMALL-NEXT: target-flags(riscv-tprel-hi) @t_ie +; RV32-SMALL-NEXT: target-flags(riscv-tprel-add) @t_ie +; RV32-SMALL-NEXT: target-flags(riscv-tprel-lo) @t_ie +; RV32-SMALL-NEXT: target-flags(riscv-tprel-hi) @t_le +; RV32-SMALL-NEXT: target-flags(riscv-tprel-add) @t_le +; RV32-SMALL-NEXT: target-flags(riscv-tprel-lo) @t_le +; RV32-SMALL: target-flags(riscv-call) @callee +; +; RV32-MED-LABEL: name: caller +; RV32-MED: target-flags(riscv-got-hi) @g_e +; RV32-MED-NEXT: target-flags(riscv-pcrel-lo) %bb.1 +; RV32-MED: target-flags(riscv-pcrel-hi) @g_i +; RV32-MED-NEXT: target-flags(riscv-pcrel-lo) %bb.2 +; RV32-MED: target-flags(riscv-tls-gd-hi) @t_un +; RV32-MED-NEXT: target-flags(riscv-pcrel-lo) %bb.3 +; RV32-MED-NEXT: target-flags(riscv-plt) &__tls_get_addr +; RV32-MED: target-flags(riscv-tls-gd-hi) @t_ld +; RV32-MED-NEXT: target-flags(riscv-pcrel-lo) %bb.4 +; RV32-MED-NEXT: target-flags(riscv-plt) &__tls_get_addr +; RV32-MED: target-flags(riscv-tls-got-hi) @t_ie +; RV32-MED-NEXT: target-flags(riscv-pcrel-lo) %bb.5 +; RV32-MED: target-flags(riscv-tprel-hi) @t_le +; RV32-MED-NEXT: target-flags(riscv-tprel-add) @t_le +; RV32-MED-NEXT: target-flags(riscv-tprel-lo) @t_le +; RV32-MED: target-flags(riscv-plt) @callee +; + %b = load i32, i32* @g_e + %c = load i32, i32* @g_i + %d = load i32, i32* @t_un + %e = load i32, i32* @t_ld + %f = load i32, i32* @t_ie + %g = load i32, i32* @t_le + %sum = bitcast i32 0 to i32 + %sum.a = add i32 %sum, %a + %sum.b = add i32 %sum.a, %b + %sum.c = add i32 %sum.b, %c + %sum.d = add i32 %sum.c, %d + %sum.e = add i32 %sum.d, %e + %sum.f = add i32 %sum.e, %f + %sum.g = add i32 %sum.f, %g + %retval = call i32 @callee(i32 %sum.g) + ret i32 %retval +} +