[llvm-commits] [llvm] r51997 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll

Matthijs Kooijman matthijs at stdin.nl
Thu Jun 5 05:52:03 PDT 2008


Author: matthijs
Date: Thu Jun  5 07:51:53 2008
New Revision: 51997

URL: http://llvm.org/viewvc/llvm-project?rev=51997&view=rev
Log:
Learn ScalarReplAggregrates how stores and loads of first class aggregrates
work and how to replace them into individual values. Also, when trying to
replace an aggregrate that is used by load or store with a single (large)
integer, don't crash (but don't replace the aggregrate either).

Also adds a testcase for both structs and arrays.

Added:
    llvm/trunk/test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=51997&r1=51996&r2=51997&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu Jun  5 07:51:53 2008
@@ -302,6 +302,41 @@
       continue;
     }
     
+    // Replace %res = load { i32, i32 }* %alloc
+    // by
+    // %load.0 = load i32* %alloc.0
+    // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 
+    // %load.1 = load i32* %alloc.1
+    // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 
+    // (Also works for arrays instead of structs)
+    if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
+      Value *Insert = UndefValue::get(LI->getType());
+      for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) {
+        Value *Load = new LoadInst(ElementAllocas[i], "load", LI);
+        Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI);
+      }
+      LI->replaceAllUsesWith(Insert);
+      LI->eraseFromParent();
+      continue;
+    }
+
+    // Replace store { i32, i32 } %val, { i32, i32 }* %alloc
+    // by
+    // %val.0 = extractvalue { i32, i32 } %val, 0 
+    // store i32 %val.0, i32* %alloc.0
+    // %val.1 = extractvalue { i32, i32 } %val, 1 
+    // store i32 %val.1, i32* %alloc.1
+    // (Also works for arrays instead of structs)
+    if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
+      Value *Val = SI->getOperand(0);
+      for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) {
+        Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI);
+        new StoreInst(Extract, ElementAllocas[i], SI);
+      }
+      SI->eraseFromParent();
+      continue;
+    }
+    
     GetElementPtrInst *GEPI = cast<GetElementPtrInst>(User);
     // We now know that the GEP is of the form: GEP <ptr>, 0, <cst>
     unsigned Idx =
@@ -440,6 +475,12 @@
   if (BitCastInst *C = dyn_cast<BitCastInst>(User))
     return isSafeUseOfBitCastedAllocation(C, AI, Info);
 
+  if (isa<LoadInst>(User))
+    return; // Loads (returning a first class aggregrate) are always rewritable
+
+  if (isa<StoreInst>(User) && User->getOperand(0) != AI)
+    return; // Store is ok if storing INTO the pointer, not storing the pointer
+ 
   GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User);
   if (GEPI == 0)
     return MarkUnsafe(Info);
@@ -961,12 +1002,22 @@
     Instruction *User = cast<Instruction>(*UI);
     
     if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
+      // FIXME: Loads of a first class aggregrate value could be converted to a
+      // series of loads and insertvalues
+      if (!LI->getType()->isSingleValueType())
+        return 0;
+
       if (MergeInType(LI->getType(), UsedType, TD))
         return 0;
       
     } else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
       // Storing the pointer, not into the value?
       if (SI->getOperand(0) == V) return 0;
+
+      // FIXME: Stores of a first class aggregrate value could be converted to a
+      // series of extractvalues and stores
+      if (!SI->getOperand(0)->getType()->isSingleValueType())
+        return 0;
       
       // NOTE: We could handle storing of FP imms into integers here!
       

Added: llvm/trunk/test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll?rev=51997&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll (added)
+++ llvm/trunk/test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll Thu Jun  5 07:51:53 2008
@@ -0,0 +1,32 @@
+; This test shows an alloca of a struct and an array that can be reduced to
+; multiple variables easily. However, the alloca is used by a store
+; instruction, which was not possible before aggregrates were first class
+; values. This checks of scalarrepl splits up the struct and array properly.
+
+; RUN: llvm-as < %s | opt -scalarrepl | llvm-dis | not grep alloca
+
+define i32 @foo() {
+	%target = alloca { i32, i32 }		; <{ i32, i32 }*> [#uses=1]
+        ; Build a first class struct to store
+	%res1 = insertvalue { i32, i32 } undef, i32 1, 0		; <{ i32, i32 }> [#uses=1]
+	%res2 = insertvalue { i32, i32 } %res1, i32 2, 1		; <{ i32, i32 }> [#uses=1]
+        ; And store it
+	store { i32, i32 } %res2, { i32, i32 }* %target
+        ; Actually use %target, so it doesn't get removed alltogether
+        %ptr = getelementptr { i32, i32 }* %target, i32 0, i32 0
+        %val = load i32* %ptr
+	ret i32 %val
+}
+
+define i32 @bar() {
+	%target = alloca [ 2 x i32 ]		; <{ i32, i32 }*> [#uses=1]
+        ; Build a first class array to store
+	%res1 = insertvalue [ 2 x i32 ] undef, i32 1, 0		; <{ i32, i32 }> [#uses=1]
+	%res2 = insertvalue [ 2 x i32 ] %res1, i32 2, 1		; <{ i32, i32 }> [#uses=1]
+        ; And store it
+	store [ 2 x i32 ] %res2, [ 2 x i32 ]* %target
+        ; Actually use %target, so it doesn't get removed alltogether
+        %ptr = getelementptr [ 2 x i32 ]* %target, i32 0, i32 0
+        %val = load i32* %ptr
+	ret i32 %val
+}





More information about the llvm-commits mailing list