}
return false;
}
+
+std::pair<unsigned, unsigned>
+RISCVInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
+ const unsigned Mask = RISCVII::MO_DIRECT_FLAG_MASK;
+ return std::make_pair(TF & Mask, TF & ~Mask);
+}
+
+ArrayRef<std::pair<unsigned, const char *>>
+RISCVInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
+ using namespace RISCVII;
+ static const std::pair<unsigned, const char *> 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);
+}
--- /dev/null
+; 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
+}