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