From: Jiong Wang Date: Thu, 28 Feb 2019 19:21:28 +0000 (+0000) Subject: bpf: enable sub-register code-gen for XADD X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b17832255a6eaf95677f322fd834a8450bc20cff;p=llvm bpf: enable sub-register code-gen for XADD Support sub-register code-gen for XADD is like supporting any other Load and Store patterns. No new instruction is introduced. lock *(u32 *)(r1 + 0) += w2 has exactly the same underlying insn as: lock *(u32 *)(r1 + 0) += r2 BPF_W width modifier has guaranteed they behave the same at runtime. This patch merely teaches BPF back-end that BPF_W width modifier could work GPR32 register class and that's all needed for sub-register code-gen support for XADD. test/CodeGen/BPF/xadd.ll updated to include sub-register code-gen tests. A new testcase test/CodeGen/BPF/xadd_legal.ll is added to make sure the legal case could pass on all code-gen modes. It could also test dead Def check on GPR32. If there is no proper handling like what has been done inside BPFMIChecking.cpp:hasLivingDefs, then this testcase will fail. Acked-by: Yonghong Song Signed-off-by: Jiong Wang git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355126 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/BPF/BPFInstrInfo.td b/lib/Target/BPF/BPFInstrInfo.td index 36724b81fc6..c44702a78ec 100644 --- a/lib/Target/BPF/BPFInstrInfo.td +++ b/lib/Target/BPF/BPFInstrInfo.td @@ -614,11 +614,31 @@ class XADD let BPFClass = BPF_STX; } +class XADD32 + : TYPE_LD_ST { + bits<4> dst; + bits<20> addr; + + let Inst{51-48} = addr{19-16}; // base reg + let Inst{55-52} = dst; + let Inst{47-32} = addr{15-0}; // offset + let BPFClass = BPF_STX; +} + let Constraints = "$dst = $val" in { -def XADD32 : XADD; -def XADD64 : XADD; -// undefined def XADD16 : XADD<1, "xadd16", atomic_load_add_16>; -// undefined def XADD8 : XADD<2, "xadd8", atomic_load_add_8>; + let Predicates = [BPFNoALU32] in { + def XADDW : XADD; + } + + let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in { + def XADDW32 : XADD32; + } + + def XADDD : XADD; } // bswap16, bswap32, bswap64 diff --git a/lib/Target/BPF/BPFMIChecking.cpp b/lib/Target/BPF/BPFMIChecking.cpp index 514af76b845..4c46289656b 100644 --- a/lib/Target/BPF/BPFMIChecking.cpp +++ b/lib/Target/BPF/BPFMIChecking.cpp @@ -155,7 +155,9 @@ static bool hasLiveDefs(const MachineInstr &MI, const TargetRegisterInfo *TRI) { void BPFMIPreEmitChecking::checkingIllegalXADD(void) { for (MachineBasicBlock &MBB : *MF) { for (MachineInstr &MI : MBB) { - if (MI.getOpcode() != BPF::XADD32 && MI.getOpcode() != BPF::XADD64) + if (MI.getOpcode() != BPF::XADDW && + MI.getOpcode() != BPF::XADDD && + MI.getOpcode() != BPF::XADDW32) continue; LLVM_DEBUG(MI.dump()); diff --git a/test/CodeGen/BPF/xadd.ll b/test/CodeGen/BPF/xadd.ll index c5f2620179e..49f0c10c318 100644 --- a/test/CodeGen/BPF/xadd.ll +++ b/test/CodeGen/BPF/xadd.ll @@ -1,5 +1,7 @@ ; RUN: not llc -march=bpfel < %s 2>&1 | FileCheck %s ; RUN: not llc -march=bpfeb < %s 2>&1 | FileCheck %s +; RUN: not llc -march=bpfel -mattr=+alu32 < %s 2>&1 | FileCheck %s +; RUN: not llc -march=bpfeb -mattr=+alu32 < %s 2>&1 | FileCheck %s ; This file is generated with the source command and source ; $ clang -target bpf -O2 -g -S -emit-llvm t.c diff --git a/test/CodeGen/BPF/xadd_legal.ll b/test/CodeGen/BPF/xadd_legal.ll new file mode 100644 index 00000000000..0d30084af8b --- /dev/null +++ b/test/CodeGen/BPF/xadd_legal.ll @@ -0,0 +1,26 @@ +; RUN: llc -march=bpfel < %s 2>&1 | FileCheck --check-prefix=CHECK-64 %s +; RUN: llc -march=bpfeb < %s 2>&1 | FileCheck --check-prefix=CHECK-64 %s +; RUN: llc -march=bpfel -mattr=+alu32 < %s 2>&1 | FileCheck --check-prefix=CHECK-32 %s +; RUN: llc -march=bpfeb -mattr=+alu32 < %s 2>&1 | FileCheck --check-prefix=CHECK-32 %s + +; This file is generated with the source command and source +; $ clang -target bpf -O2 -S -emit-llvm t.c +; $ cat t.c +; int test(int *ptr, unsigned long long a) { +; __sync_fetch_and_add(ptr, a); +; return *ptr; +; } +; +; NOTE: passing unsigned long long as the second operand of __sync_fetch_and_add +; could effectively create sub-register reference coming from indexing a full +; register which could then exerceise hasLivingDefs inside BPFMIChecker.cpp. + +define dso_local i32 @test(i32* nocapture %ptr, i64 %a) { +entry: + %conv = trunc i64 %a to i32 + %0 = atomicrmw add i32* %ptr, i32 %conv seq_cst +; CHECK-64: lock *(u32 *)(r1 + 0) += r2 +; CHECK-32: lock *(u32 *)(r1 + 0) += w2 + %1 = load i32, i32* %ptr, align 4 + ret i32 %1 +}