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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits