diff options
author | Dan Gohman <sunfish@google.com> | 2014-02-13 19:24:56 -0800 |
---|---|---|
committer | Dan Gohman <sunfish@google.com> | 2014-02-14 11:38:16 -0800 |
commit | 71fb6dcb87d2abd302080149d4a583a5e35e3697 (patch) | |
tree | 8fd196d2d2b3ddad6188d72dbfc481395f620d19 | |
parent | f3359807242e95f9e94bb35c0d90a73c794f1af0 (diff) |
Preserve alignment information when promoting integer loads and stores.
-rw-r--r-- | lib/Transforms/NaCl/PromoteIntegers.cpp | 43 | ||||
-rw-r--r-- | test/Transforms/NaCl/promote-integer-align.ll | 29 |
2 files changed, 67 insertions, 5 deletions
diff --git a/lib/Transforms/NaCl/PromoteIntegers.cpp b/lib/Transforms/NaCl/PromoteIntegers.cpp index d48bdfc37b..b8050b5ba2 100644 --- a/lib/Transforms/NaCl/PromoteIntegers.cpp +++ b/lib/Transforms/NaCl/PromoteIntegers.cpp @@ -43,13 +43,25 @@ using namespace llvm; namespace { +class ConversionState; + class PromoteIntegers : public FunctionPass { + DataLayout *DL; + + Value *splitLoad(LoadInst *Inst, ConversionState &State); + Value *splitStore(StoreInst *Inst, ConversionState &State); + void convertInstruction(Instruction *Inst, ConversionState &State); + public: static char ID; PromoteIntegers() : FunctionPass(ID) { initializePromoteIntegersPass(*PassRegistry::getPassRegistry()); } virtual bool runOnFunction(Function &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<DataLayout>(); + return FunctionPass::getAnalysisUsage(AU); + } }; } @@ -135,6 +147,8 @@ static Value *convertConstant(Constant *C, bool SignExt=false) { } } +namespace { + // Holds the state for converting/replacing values. Conversion is done in one // pass, with each value requiring conversion possibly having two stages. When // an instruction needs to be replaced (i.e. it has illegal operands or result) @@ -212,9 +226,11 @@ class ConversionState { SmallVector<Instruction *, 8> ToErase; }; +} // anonymous namespace + // Split an illegal load into multiple legal loads and return the resulting // promoted value. The size of the load is assumed to be a multiple of 8. -static Value *splitLoad(LoadInst *Inst, ConversionState &State) { +Value *PromoteIntegers::splitLoad(LoadInst *Inst, ConversionState &State) { if (Inst->isVolatile() || Inst->isAtomic()) report_fatal_error("Can't split volatile/atomic loads"); if (cast<IntegerType>(Inst->getType())->getBitWidth() % 8 != 0) @@ -246,7 +262,15 @@ static Value *splitLoad(LoadInst *Inst, ConversionState &State) { HiType->getPointerTo(), OrigPtr->getName() + ".hity"); - Value *LoadHi = IRB.CreateAlignedLoad(BCHi, 1, Inst->getName() + ".hi"); // XXX EMSCRIPTEN: worst-case alignment assumption +#if 0 // XXX EMSCRIPTEN: We want the full-strength alignment. + Value *LoadHi = IRB.CreateAlignedLoad(BCHi, 1, Inst->getName() + ".hi"); +#else + unsigned HiAlign = MinAlign(Inst->getAlignment() == 0 ? + DL->getABITypeAlignment(Inst->getType()) : + Inst->getAlignment(), + LoWidth / 8); + Value *LoadHi = IRB.CreateAlignedLoad(BCHi, HiAlign, Inst->getName() + ".hi"); +#endif if (!isLegalSize(Width - LoWidth)) { LoadHi = splitLoad(cast<LoadInst>(LoadHi), State); #if 0 /// XXX EMSCRIPTEN: We don't need to convert pointers. @@ -266,7 +290,7 @@ static Value *splitLoad(LoadInst *Inst, ConversionState &State) { return Result; } -static Value *splitStore(StoreInst *Inst, ConversionState &State) { +Value *PromoteIntegers::splitStore(StoreInst *Inst, ConversionState &State) { if (Inst->isVolatile() || Inst->isAtomic()) report_fatal_error("Can't split volatile/atomic stores"); if (cast<IntegerType>(Inst->getValueOperand()->getType())->getBitWidth() % 8 @@ -305,7 +329,15 @@ static Value *splitStore(StoreInst *Inst, ConversionState &State) { HiType->getPointerTo(), OrigPtr->getName() + ".hity"); - Value *StoreHi = IRB.CreateAlignedStore(HiTrunc, BCHi, 1); // XXX EMSCRIPTEN: worst-case alignment assumption +#if 0 // XXX EMSCRIPTEN: We want the full-strength alignment. + Value *StoreHi = IRB.CreateAlignedStore(HiTrunc, BCHi, 1); +#else + unsigned HiAlign = MinAlign(Inst->getAlignment() == 0 ? + DL->getABITypeAlignment(Inst->getValueOperand()->getType()) : + Inst->getAlignment(), + LoWidth / 8); + Value *StoreHi = IRB.CreateAlignedStore(HiTrunc, BCHi, HiAlign); +#endif if (!isLegalSize(Width - LoWidth)) { // HiTrunc is still illegal, and is redundant with the truncate in the @@ -389,7 +421,7 @@ static Value *getSignExtend(Value *Operand, Value *OrigOperand, InsertPt), Shl); } -static void convertInstruction(Instruction *Inst, ConversionState &State) { +void PromoteIntegers::convertInstruction(Instruction *Inst, ConversionState &State) { if (SExtInst *Sext = dyn_cast<SExtInst>(Inst)) { Value *Op = Sext->getOperand(0); Value *NewInst = NULL; @@ -642,6 +674,7 @@ static void convertInstruction(Instruction *Inst, ConversionState &State) { } bool PromoteIntegers::runOnFunction(Function &F) { + DL = &getAnalysis<DataLayout>(); // Don't support changing the function arguments. This should not be // generated by clang. for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { diff --git a/test/Transforms/NaCl/promote-integer-align.ll b/test/Transforms/NaCl/promote-integer-align.ll new file mode 100644 index 0000000000..0866d99a72 --- /dev/null +++ b/test/Transforms/NaCl/promote-integer-align.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -nacl-promote-ints < %s | FileCheck %s + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" + +; CHECK: define void @aligned_copy(i24* %p, i24* %q) { +; CHECK-NEXT: %p.loty = bitcast i24* %p to i16* +; CHECK-NEXT: %t.lo = load i16* %p.loty, align 64 +; CHECK-NEXT: %t.lo.ext = zext i16 %t.lo to i32 +; CHECK-NEXT: %p.hi = getelementptr i16* %p.loty, i32 1 +; CHECK-NEXT: %p.hity = bitcast i16* %p.hi to i8* +; CHECK-NEXT: %t.hi = load i8* %p.hity, align 1 +; CHECK-NEXT: %t.hi.ext = zext i8 %t.hi to i32 +; CHECK-NEXT: %t.hi.ext.sh = shl i32 %t.hi.ext, 16 +; CHECK-NEXT: %t = or i32 %t.lo.ext, %t.hi.ext.sh +; CHECK-NEXT: %q.loty = bitcast i24* %q to i16* +; CHECK-NEXT: %t.lo1 = trunc i32 %t to i16 +; CHECK-NEXT: store i16 %t.lo1, i16* %q.loty, align 64 +; CHECK-NEXT: %t.hi.sh = lshr i32 %t, 16 +; CHECK-NEXT: %q.hi = getelementptr i16* %q.loty, i32 1 +; CHECK-NEXT: %t.hi2 = trunc i32 %t.hi.sh to i8 +; CHECK-NEXT: %q.hity = bitcast i16* %q.hi to i8* +; CHECK-NEXT: store i8 %t.hi2, i8* %q.hity, align 1 +; CHECK-NEXT: ret void +; CHECK-NEXT:} +define void @aligned_copy(i24* %p, i24* %q) { + %t = load i24* %p, align 64 + store i24 %t, i24* %q, align 64 + ret void +} |