From: Chris Lattner Date: Sun, 19 Sep 2004 18:43:46 +0000 (+0000) Subject: Make instruction combining a bit more aggressive in the face of volatile X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c10acedb2d1758742099cc19e476b9562c4e6aac;p=oota-llvm.git Make instruction combining a bit more aggressive in the face of volatile loads, and implement two new transforms: InstCombine/load.ll:test[56]. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16404 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 2340c49b563..ee886374a3d 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -2983,7 +2983,8 @@ static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI) { // the same size. Instead of casting the pointer before the load, cast // the result of the loaded value. Value *NewLoad = IC.InsertNewInstBefore(new LoadInst(CI->getOperand(0), - CI->getName()), LI); + CI->getName(), + LI.isVolatile()),LI); // Now cast the result of the load. return new CastInst(NewLoad, LI.getType()); } @@ -2991,12 +2992,17 @@ static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI) { return 0; } +/// isSafeToLoadUnconditionally - Return true if we know that executing a load +/// from this value cannot trap. +static bool isSafeToLoadUnconditionally(Value *V) { + return isa(V) || isa(V); +} + Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { Value *Op = LI.getOperand(0); - if (LI.isVolatile()) return 0; if (Constant *C = dyn_cast(Op)) - if (C->isNullValue()) // load null -> 0 + if (C->isNullValue() && !LI.isVolatile()) // load null -> 0 return ReplaceInstUsesWith(LI, Constant::getNullValue(LI.getType())); // Instcombine load (constant global) into the value loaded... @@ -3021,6 +3027,57 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { if (Instruction *Res = InstCombineLoadCast(*this, LI)) return Res; + if (!LI.isVolatile() && Op->hasOneUse()) { + // Change select and PHI nodes to select values instead of addresses: this + // helps alias analysis out a lot, allows many others simplifications, and + // exposes redundancy in the code. + // + // Note that we cannot do the transformation unless we know that the + // introduced loads cannot trap! Something like this is valid as long as + // the condition is always false: load (select bool %C, int* null, int* %G), + // but it would not be valid if we transformed it to load from null + // unconditionally. + // + if (SelectInst *SI = dyn_cast(Op)) { + // load (select (Cond, &V1, &V2)) --> select(Cond, load &V1, load &V2). + if (isSafeToLoadUnconditionally(SI->getOperand(1)) && + isSafeToLoadUnconditionally(SI->getOperand(2))) { + Value *V1 = InsertNewInstBefore(new LoadInst(SI->getOperand(1), + SI->getOperand(1)->getName()+".val"), *SI); + Value *V2 = InsertNewInstBefore(new LoadInst(SI->getOperand(2), + SI->getOperand(2)->getName()+".val"), *SI); + return new SelectInst(SI->getCondition(), V1, V2); + } + + } else if (PHINode *PN = dyn_cast(Op)) { + // load (phi (&V1, &V2, &V3)) --> phi(load &V1, load &V2, load &V3) + bool Safe = true; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (!isSafeToLoadUnconditionally(PN->getIncomingValue(i))) { + Safe = false; + break; + } + if (Safe) { + // Create the PHI. + PHINode *NewPN = new PHINode(LI.getType(), PN->getName()); + InsertNewInstBefore(NewPN, *PN); + std::map LoadMap; // Don't insert duplicate loads + + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *BB = PN->getIncomingBlock(i); + Value *&TheLoad = LoadMap[BB]; + if (TheLoad == 0) { + Value *InVal = PN->getIncomingValue(i); + TheLoad = InsertNewInstBefore(new LoadInst(InVal, + InVal->getName()+".val"), + *BB->getTerminator()); + } + NewPN->addIncoming(TheLoad, BB); + } + return ReplaceInstUsesWith(LI, NewPN); + } + } + } return 0; }