[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner lattner at cs.uiuc.edu
Sun Sep 19 11:43:57 PDT 2004



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.240 -> 1.241
---
Log message:

Make instruction combining a bit more aggressive in the face of volatile
loads, and implement two new transforms: InstCombine/load.ll:test[56].



---
Diffs of the changes:  (+60 -3)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.240 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.241
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.240	Wed Sep  1 17:55:36 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Sun Sep 19 13:43:46 2004
@@ -2983,7 +2983,8 @@
       // 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 @@
   return 0;
 }
 
+/// isSafeToLoadUnconditionally - Return true if we know that executing a load
+/// from this value cannot trap.
+static bool isSafeToLoadUnconditionally(Value *V) {
+  return isa<AllocaInst>(V) || isa<GlobalVariable>(V);
+}
+
 Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
   Value *Op = LI.getOperand(0);
-  if (LI.isVolatile()) return 0;
 
   if (Constant *C = dyn_cast<Constant>(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 @@
     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<SelectInst>(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<PHINode>(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<BasicBlock*,Value*> 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;
 }
 






More information about the llvm-commits mailing list