summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/InlineCost.cpp5
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp61
-rw-r--r--llvm/lib/CodeGen/CMakeLists.txt1
-rw-r--r--llvm/lib/CodeGen/CodeGen.cpp1
-rw-r--r--llvm/lib/CodeGen/LLVMTargetMachine.cpp2
-rw-r--r--llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp85
6 files changed, 155 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index aa46b68d8c3..ee36c6e5486 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -900,6 +900,11 @@ bool CallAnalyzer::visitCallSite(CallSite CS) {
default:
return Base::visitCallSite(CS);
+ case Intrinsic::load_relative:
+ // This is normally lowered to 4 LLVM instructions.
+ Cost += 3 * InlineConstants::InstrCost;
+ return false;
+
case Intrinsic::memset:
case Intrinsic::memcpy:
case Intrinsic::memmove:
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index b34aede2d3c..b9e6bdbf2e5 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -3825,6 +3825,62 @@ static bool IsIdempotent(Intrinsic::ID ID) {
}
}
+static Value *SimplifyRelativeLoad(Constant *Ptr, Constant *Offset,
+ const DataLayout &DL) {
+ GlobalValue *PtrSym;
+ APInt PtrOffset;
+ if (!IsConstantOffsetFromGlobal(Ptr, PtrSym, PtrOffset, DL))
+ return nullptr;
+
+ Type *Int8PtrTy = Type::getInt8PtrTy(Ptr->getContext());
+ Type *Int32Ty = Type::getInt32Ty(Ptr->getContext());
+ Type *Int32PtrTy = Int32Ty->getPointerTo();
+ Type *Int64Ty = Type::getInt64Ty(Ptr->getContext());
+
+ auto *OffsetConstInt = dyn_cast<ConstantInt>(Offset);
+ if (!OffsetConstInt || OffsetConstInt->getType()->getBitWidth() > 64)
+ return nullptr;
+
+ uint64_t OffsetInt = OffsetConstInt->getSExtValue();
+ if (OffsetInt % 4 != 0)
+ return nullptr;
+
+ Constant *C = ConstantExpr::getGetElementPtr(
+ Int32Ty, ConstantExpr::getBitCast(Ptr, Int32PtrTy),
+ ConstantInt::get(Int64Ty, OffsetInt / 4));
+ Constant *Loaded = ConstantFoldLoadFromConstPtr(C, Int32Ty, DL);
+ if (!Loaded)
+ return nullptr;
+
+ auto *LoadedCE = dyn_cast<ConstantExpr>(Loaded);
+ if (!LoadedCE)
+ return nullptr;
+
+ if (LoadedCE->getOpcode() == Instruction::Trunc) {
+ LoadedCE = dyn_cast<ConstantExpr>(LoadedCE->getOperand(0));
+ if (!LoadedCE)
+ return nullptr;
+ }
+
+ if (LoadedCE->getOpcode() != Instruction::Sub)
+ return nullptr;
+
+ auto *LoadedLHS = dyn_cast<ConstantExpr>(LoadedCE->getOperand(0));
+ if (!LoadedLHS || LoadedLHS->getOpcode() != Instruction::PtrToInt)
+ return nullptr;
+ auto *LoadedLHSPtr = LoadedLHS->getOperand(0);
+
+ Constant *LoadedRHS = LoadedCE->getOperand(1);
+ GlobalValue *LoadedRHSSym;
+ APInt LoadedRHSOffset;
+ if (!IsConstantOffsetFromGlobal(LoadedRHS, LoadedRHSSym, LoadedRHSOffset,
+ DL) ||
+ PtrSym != LoadedRHSSym || PtrOffset != LoadedRHSOffset)
+ return nullptr;
+
+ return ConstantExpr::getBitCast(LoadedLHSPtr, Int8PtrTy);
+}
+
template <typename IterTy>
static Value *SimplifyIntrinsic(Function *F, IterTy ArgBegin, IterTy ArgEnd,
const Query &Q, unsigned MaxRecurse) {
@@ -3865,6 +3921,11 @@ static Value *SimplifyIntrinsic(Function *F, IterTy ArgBegin, IterTy ArgEnd,
if (match(RHS, m_Undef()))
return Constant::getNullValue(ReturnType);
}
+
+ if (IID == Intrinsic::load_relative && isa<Constant>(LHS) &&
+ isa<Constant>(RHS))
+ return SimplifyRelativeLoad(cast<Constant>(LHS), cast<Constant>(RHS),
+ Q.DL);
}
// Perform idempotent optimizations
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index aab4088eb9a..0717c3beefe 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -87,6 +87,7 @@ add_llvm_library(LLVMCodeGen
PHIEliminationUtils.cpp
PostRAHazardRecognizer.cpp
PostRASchedulerList.cpp
+ PreISelIntrinsicLowering.cpp
ProcessImplicitDefs.cpp
PrologEpilogInserter.cpp
PseudoSourceValue.cpp
diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index ca3b36c17f1..7ab69d7c326 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -63,6 +63,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializePostMachineSchedulerPass(Registry);
initializePostRAHazardRecognizerPass(Registry);
initializePostRASchedulerPass(Registry);
+ initializePreISelIntrinsicLoweringPass(Registry);
initializeProcessImplicitDefsPass(Registry);
initializeRegisterCoalescerPass(Registry);
initializeShrinkWrapPass(Registry);
diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
index a19049360c0..ea113c894cf 100644
--- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp
@@ -102,6 +102,8 @@ addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM,
if (TM->Options.EmulatedTLS)
PM.add(createLowerEmuTLSPass(TM));
+ PM.add(createPreISelIntrinsicLoweringPass());
+
// Add internal analysis passes from the target machine.
PM.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
new file mode 100644
index 00000000000..a1ff231412d
--- /dev/null
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -0,0 +1,85 @@
+//===-- PreISelIntrinsicLowering.cpp - Pre-ISel intrinsic lowering pass ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass implements IR lowering for the llvm.load.relative intrinsic.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+
+using namespace llvm;
+
+namespace {
+
+bool lowerLoadRelative(Function &F) {
+ if (F.use_empty())
+ return false;
+
+ bool Changed = false;
+ Type *Int32Ty = Type::getInt32Ty(F.getContext());
+ Type *Int32PtrTy = Int32Ty->getPointerTo();
+ Type *Int8Ty = Type::getInt8Ty(F.getContext());
+
+ for (auto I = F.use_begin(), E = F.use_end(); I != E;) {
+ auto CI = dyn_cast<CallInst>(I->getUser());
+ ++I;
+ if (!CI || CI->getCalledValue() != &F)
+ continue;
+
+ IRBuilder<> B(CI);
+ Value *OffsetPtr =
+ B.CreateGEP(Int8Ty, CI->getArgOperand(0), CI->getArgOperand(1));
+ Value *OffsetPtrI32 = B.CreateBitCast(OffsetPtr, Int32PtrTy);
+ Value *OffsetI32 = B.CreateAlignedLoad(OffsetPtrI32, 4);
+
+ Value *ResultPtr = B.CreateGEP(Int8Ty, CI->getArgOperand(0), OffsetI32);
+
+ CI->replaceAllUsesWith(ResultPtr);
+ CI->eraseFromParent();
+ Changed = true;
+ }
+
+ return Changed;
+}
+
+bool lowerIntrinsics(Module &M) {
+ bool Changed = false;
+ for (Function &F : M) {
+ if (F.getName().startswith("llvm.load.relative."))
+ Changed |= lowerLoadRelative(F);
+ }
+ return Changed;
+}
+
+class PreISelIntrinsicLowering : public ModulePass {
+public:
+ static char ID;
+ PreISelIntrinsicLowering() : ModulePass(ID) {}
+
+ bool runOnModule(Module &M) {
+ return lowerIntrinsics(M);
+ }
+};
+
+char PreISelIntrinsicLowering::ID;
+
+}
+
+INITIALIZE_PASS(PreISelIntrinsicLowering, "pre-isel-intrinsic-lowering",
+ "Pre-ISel Intrinsic Lowering", false, false)
+
+ModulePass *llvm::createPreISelIntrinsicLoweringPass() {
+ return new PreISelIntrinsicLowering;
+}
OpenPOWER on IntegriCloud