Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Unified Diff: lib/Transforms/NaCl/ConstantInsertExtractElementIndex.cpp

Issue 221693002: PNaCl: Add support for GCC/LLVM vector extensions (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Remove TODOs that were done. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/Transforms/NaCl/ConstantInsertExtractElementIndex.cpp
diff --git a/lib/Transforms/NaCl/ConstantInsertExtractElementIndex.cpp b/lib/Transforms/NaCl/ConstantInsertExtractElementIndex.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ac70b8efa732466cbec8c5f0e9de1cf1a9790b16
--- /dev/null
+++ b/lib/Transforms/NaCl/ConstantInsertExtractElementIndex.cpp
@@ -0,0 +1,153 @@
+//===- ConstantInsertExtractElementIndex.cpp - Insert/Extract element -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Transform all InsertElement and ExtractElement with non-constant or
+// out-of-bounds indices into stack accesses. This moves all undefined
+// behavior to the stack, making InsertElement and ExtractElement
+// well-defined.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/NaCl.h"
+
+#include <algorithm>
+
+using namespace llvm;
+
+namespace {
+class ConstantInsertExtractElementIndex : public BasicBlockPass {
+public:
+ static char ID; // Pass identification, replacement for typeid
+ ConstantInsertExtractElementIndex() : BasicBlockPass(ID), M(0), TD(0) {
+ initializeConstantInsertExtractElementIndexPass(
+ *PassRegistry::getPassRegistry());
+ }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<DataLayout>();
+ BasicBlockPass::getAnalysisUsage(AU);
+ }
+ virtual bool doInitialization(Module &Mod) {
+ M = &Mod;
+ return false; // Unchanged.
+ }
+ virtual bool runOnBasicBlock(BasicBlock &BB);
+
+private:
+ typedef SmallVector<Instruction *, 8> Instructions;
+ const Module *M;
+ const DataLayout *TD;
jvoung (off chromium) 2014/04/04 23:20:21 I think TargetData was renamed to DataLayout. Some
JF 2014/04/15 01:52:27 Done, in this and other files.
+
+ /// Get the index of an InsertElement or ExtractElement instruction, or null.
+ static Value *getIdx(const Instruction *I);
+
+ void findInvalidInsertExtractElements(const BasicBlock &BB,
jvoung (off chromium) 2014/04/04 23:20:21 nit: It's not actually invalid so "Invalid" should
JF 2014/04/15 01:52:27 Done.
+ Instructions &BadVectorIdx) const;
+ void fixInvalidInsertExtractElements(BasicBlock &BB,
+ const Instructions &BadVectorIdx) const;
+};
+}
+
+char ConstantInsertExtractElementIndex::ID = 0;
+INITIALIZE_PASS(
+ ConstantInsertExtractElementIndex, "constant-insert-extract-element-index",
+ "Force insert and extract vector elemement to always be in bounds", false,
jvoung (off chromium) 2014/04/04 23:20:21 elemement -> element This doesn't really force th
JF 2014/04/15 01:52:27 Correct. I don't mind doing what you suggest inste
jvoung (off chromium) 2014/04/16 00:10:27 Sure, I'm okay with leaving this as is for now, si
+ false)
+
+Value *ConstantInsertExtractElementIndex::getIdx(const Instruction *I) {
jvoung (off chromium) 2014/04/04 23:20:21 Could have just been a static function that's not
JF 2014/04/15 01:52:27 Done.
+ switch (I->getOpcode()) {
+ default: return 0;
Jim Stichnoth 2014/04/04 23:08:17 I don't know of a style guide reference, but could
JF 2014/04/15 01:52:27 Done.
+ case Instruction::InsertElement: return I->getOperand(2);
+ case Instruction::ExtractElement: return I->getOperand(1);
+ }
+}
+
+void ConstantInsertExtractElementIndex::findInvalidInsertExtractElements(
+ const BasicBlock &BB, Instructions &BadVectorIdx) const {
jvoung (off chromium) 2014/04/04 23:20:21 nit: BadVectorIdx sounds like it's a single index,
JF 2014/04/15 01:52:27 Done.
+ for (BasicBlock::const_iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE;
+ ++BBI) {
+ const Instruction *I = &*BBI;
+ Value *Idx = getIdx(I);
+ if (!Idx)
+ // Not and InsertElement or ExtractElement, ignore the instruction.
Jim Stichnoth 2014/04/04 23:08:17 and --> an
JF 2014/04/15 01:52:27 Done.
+ continue;
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) {
+ unsigned NumElements =
+ cast<VectorType>(I->getOperand(0)->getType())->getNumElements();
+ if (CI->getValue().ult(NumElements))
+ // Index is constant in-range for the vector type, keep as-is.
+ continue;
+ }
+ BadVectorIdx.push_back(const_cast<Instruction *>(I));
Jim Stichnoth 2014/04/04 23:08:17 I trust const_cast is actually necessary :(
JF 2014/04/15 01:52:27 Yeah, I wanted to go all const-correctness, but so
+ }
+}
+
+void ConstantInsertExtractElementIndex::fixInvalidInsertExtractElements(
+ BasicBlock &BB, const Instructions &BadVectorIdx) const {
+ for (Instructions::const_iterator IB = BadVectorIdx.begin(),
+ IE = BadVectorIdx.end();
+ IB != IE; ++IB) {
+ Instruction *I = *IB;
+ Value *Vec = I->getOperand(0);
+ Value *Idx = getIdx(I);
+ VectorType *VecTy = cast<VectorType>(Vec->getType());
+ Type *ElemTy = VecTy->getElementType();
+ unsigned ElemAlign = TD->getPrefTypeAlignment(ElemTy);
+ unsigned VecAlign = std::max(ElemAlign, TD->getPrefTypeAlignment(VecTy));
+
+ IRBuilder<> IRB(I);
+ AllocaInst *Alloca = IRB.CreateAlloca(
+ ElemTy, ConstantInt::get(Type::getInt32Ty(M->getContext()),
jvoung (off chromium) 2014/04/04 23:20:21 Instead of ElemTy, have the alloca be i8, and mult
jvoung (off chromium) 2014/04/07 15:40:11 n/m about this point -- it'll be handled by the Re
JF 2014/04/15 01:52:27 Yeah I wanted to do the "right" thing for LLVM, an
+ VecTy->getNumElements()));
+ Alloca->setAlignment(VecAlign);
+ Value *AllocaAsVec = IRB.CreateBitCast(Alloca, VecTy->getPointerTo());
+ IRB.CreateAlignedStore(Vec, AllocaAsVec, Alloca->getAlignment());
+ Value *GEP = IRB.CreateGEP(Alloca, Idx);
+
+ Value *Res;
+ switch (I->getOpcode()) {
+ default:
+ llvm_unreachable("expected InsertElement or ExtractElement");
+ case Instruction::InsertElement: {
+ IRB.CreateAlignedStore(I->getOperand(1), GEP, ElemAlign);
+ Res = IRB.CreateAlignedLoad(AllocaAsVec, Alloca->getAlignment());
+ break;
+ }
+ case Instruction::ExtractElement: {
+ Res = IRB.CreateAlignedLoad(GEP, ElemAlign);
+ break;
+ }
+ }
Jim Stichnoth 2014/04/04 23:08:17 Sorry, these two perfectly aligned braces really b
JF 2014/04/15 01:52:27 Done, though if they *had* been required I'd have
+
+ I->replaceAllUsesWith(Res);
jvoung (off chromium) 2014/04/04 23:20:21 CopyDebug?
JF 2014/04/15 01:52:27 I was going to fix IRBuilder instead so it copies
+ I->eraseFromParent();
+ }
+}
+
+bool ConstantInsertExtractElementIndex::runOnBasicBlock(BasicBlock &BB) {
+ bool Changed = false;
+ if (!TD)
+ TD = &getAnalysis<DataLayout>();
+ Instructions BadVectorIdx;
+ findInvalidInsertExtractElements(BB, BadVectorIdx);
+ if (!BadVectorIdx.empty()) {
+ Changed = true;
+ fixInvalidInsertExtractElements(BB, BadVectorIdx);
+ }
+ return Changed;
+}
+
+BasicBlockPass *llvm::createConstantInsertExtractElementIndexPass() {
+ return new ConstantInsertExtractElementIndex();
+}

Powered by Google App Engine
This is Rietveld 408576698