yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added subscribers: llvm-commits, cfe-commits, hiraditya.
Herald added projects: clang, LLVM.

This patch tries to partially prevent speculative code motion for BPF.

First, some use cases on why we want to prevent speculative code motion.

Use case 1: bpf map value or some other data with a range.

  data = bpf_map_lookup_elem(&map, &key);
  if (!data) return 0;
  payload = data->payload;
  len = bpf_probe_read_kernel_str(payload, 16, &task->comm);
  if (len <= 16) 
    payload += len;
  ... 

The compiler may generate code like:

  data = bpf_map_lookup_elem(&map, &key);
  if (!data) return 0;
  payload = data->payload;
  len = bpf_probe_read_kernel_str(payload, 16, &task->comm);
  new_payload = payload + len;
  if (len > 16) 
    new_payload = payload
  ... 

The "payload + len" may cause kernel verifier failure as
the "len" can be anything at this moment.

Use case 2: CO-RE relocatons

  field_exist = ... 
  if (field_exist) {
    offset = non-memory-access-builtin-expr1;
  } else {
    offset = non-memory-access-builtin-expr2;
  }   
  use "offset" to read kernel memory

The compiler may generate code like:

  field_exist = ... 
  offset = non-memory-access-builtin-expr1;
  if (!field_exist)
    offset = non-memory-access-builtin-expr2;
  use "offset" to read kernel memory

This may cause failures since if field_exist is false and 
libbpf is not able to perform relation
for "offset = non-memory-access-builtin-expr1".
The instruction itself will be rewritten as
an illegal instruction and this will cause
program load failures.

To address the above issues, people use

  . inline assembly
  . artificial complex control flow

to prevent the above optimizations.

This patch tries to do with a more user friendly way.
BPF backend TargetTransformInfo implements getUserCost()
to return UserCost INT_MAX for TCK_SizeAndLatency
to prevent compiler moving codes speculatively.
An option "adjustopt", false by default, is added to
enable this adjustment.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82112

Files:
  clang/lib/Basic/Targets/BPF.h
  llvm/lib/Target/BPF/BPF.td
  llvm/lib/Target/BPF/BPFSubtarget.cpp
  llvm/lib/Target/BPF/BPFSubtarget.h
  llvm/lib/Target/BPF/BPFTargetMachine.cpp
  llvm/lib/Target/BPF/BPFTargetMachine.h
  llvm/lib/Target/BPF/BPFTargetTransformInfo.h

Index: llvm/lib/Target/BPF/BPFTargetTransformInfo.h
===================================================================
--- /dev/null
+++ llvm/lib/Target/BPF/BPFTargetTransformInfo.h
@@ -0,0 +1,51 @@
+//===------ BPFTargetTransformInfo.h - BPF specific TTI ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file a TargetTransformInfo::Concept conforming object specific to the
+// BPF target machine. It uses the target's detailed information to
+// provide more precise answers to certain TTI queries, while letting the
+// target independent and default TTI implementations handle the rest.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_BPF_BPFTARGETTRANSFORMINFO_H
+#define LLVM_LIB_TARGET_BPF_BPFTARGETTRANSFORMINFO_H
+
+#include "BPFTargetMachine.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/BasicTTIImpl.h"
+
+namespace llvm {
+class BPFTTIImpl : public BasicTTIImplBase<BPFTTIImpl> {
+  typedef BasicTTIImplBase<BPFTTIImpl> BaseT;
+  typedef TargetTransformInfo TTI;
+  friend BaseT;
+
+  const BPFSubtarget *ST;
+  const BPFTargetLowering *TLI;
+
+  const BPFSubtarget *getST() const { return ST; }
+  const BPFTargetLowering *getTLI() const { return TLI; }
+
+public:
+  explicit BPFTTIImpl(const BPFTargetMachine *TM, const Function &F)
+      : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)),
+        TLI(ST->getTargetLowering()) {}
+
+  unsigned getUserCost(const User *U, ArrayRef<const Value *> Operands,
+                       TTI::TargetCostKind CostKind) {
+    if (!ST->getHasAdjustOpt() || CostKind != TTI::TCK_SizeAndLatency)
+      return BaseT::getUserCost(U, Operands, CostKind);
+
+    return INT_MAX;
+  }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_BPF_BPFTARGETTRANSFORMINFO_H
Index: llvm/lib/Target/BPF/BPFTargetMachine.h
===================================================================
--- llvm/lib/Target/BPF/BPFTargetMachine.h
+++ llvm/lib/Target/BPF/BPFTargetMachine.h
@@ -34,6 +34,8 @@
 
   TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
 
+  TargetTransformInfo getTargetTransformInfo(const Function &F) override;
+
   TargetLoweringObjectFile *getObjFileLowering() const override {
     return TLOF.get();
   }
Index: llvm/lib/Target/BPF/BPFTargetMachine.cpp
===================================================================
--- llvm/lib/Target/BPF/BPFTargetMachine.cpp
+++ llvm/lib/Target/BPF/BPFTargetMachine.cpp
@@ -12,8 +12,11 @@
 
 #include "BPFTargetMachine.h"
 #include "BPF.h"
+#include "BPFTargetTransformInfo.h"
 #include "MCTargetDesc/BPFMCAsmInfo.h"
 #include "TargetInfo/BPFTargetInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/BasicTTIImpl.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/CodeGen/TargetPassConfig.h"
@@ -95,6 +98,11 @@
   return new BPFPassConfig(*this, PM);
 }
 
+TargetTransformInfo
+BPFTargetMachine::getTargetTransformInfo(const Function &F) {
+  return TargetTransformInfo(BPFTTIImpl(this, F));
+}
+
 void BPFPassConfig::addIRPasses() {
 
   addPass(createBPFAdjustOpt());
Index: llvm/lib/Target/BPF/BPFSubtarget.h
===================================================================
--- llvm/lib/Target/BPF/BPFSubtarget.h
+++ llvm/lib/Target/BPF/BPFSubtarget.h
@@ -57,6 +57,9 @@
   // whether we should enable MCAsmInfo DwarfUsesRelocationsAcrossSections
   bool UseDwarfRIS;
 
+  // whether to adjust optimization for verifier friendly codes
+  bool HasAdjustOpt;
+
 public:
   // This constructor initializes the data members to match that
   // of the specified triple.
@@ -72,6 +75,7 @@
   bool getHasJmp32() const { return HasJmp32; }
   bool getHasAlu32() const { return HasAlu32; }
   bool getUseDwarfRIS() const { return UseDwarfRIS; }
+  bool getHasAdjustOpt() const { return HasAdjustOpt; }
 
   const BPFInstrInfo *getInstrInfo() const override { return &InstrInfo; }
   const BPFFrameLowering *getFrameLowering() const override {
Index: llvm/lib/Target/BPF/BPFSubtarget.cpp
===================================================================
--- llvm/lib/Target/BPF/BPFSubtarget.cpp
+++ llvm/lib/Target/BPF/BPFSubtarget.cpp
@@ -38,6 +38,7 @@
   HasJmp32 = false;
   HasAlu32 = false;
   UseDwarfRIS = false;
+  HasAdjustOpt = false;
 }
 
 void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
Index: llvm/lib/Target/BPF/BPF.td
===================================================================
--- llvm/lib/Target/BPF/BPF.td
+++ llvm/lib/Target/BPF/BPF.td
@@ -32,6 +32,9 @@
 def DwarfRIS: SubtargetFeature<"dwarfris", "UseDwarfRIS", "true",
                                "Disable MCAsmInfo DwarfUsesRelocationsAcrossSections">;
 
+def AdjustOpt : SubtargetFeature<"adjustopt", "HasAdjustOpt", "true",
+                                 "Adjust Optimizations for Verifier Friendly Code">;
+
 def BPFInstPrinter : AsmWriter {
   string AsmWriterClassName  = "InstPrinter";
   bit isMCAsmWriter = 1;
Index: clang/lib/Basic/Targets/BPF.h
===================================================================
--- clang/lib/Basic/Targets/BPF.h
+++ clang/lib/Basic/Targets/BPF.h
@@ -48,7 +48,8 @@
                         MacroBuilder &Builder) const override;
 
   bool hasFeature(StringRef Feature) const override {
-    return Feature == "bpf" || Feature == "alu32" || Feature == "dwarfris";
+    return Feature == "bpf" || Feature == "alu32" || Feature == "dwarfris" ||
+           Feature == "adjustopt";
   }
 
   void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to