[PATCH] D22269: [SCCP] Replace structs with constants if all the lattice values are constant

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 12 10:44:57 PDT 2016


davide created this revision.
davide added a reviewer: eli.friedman.
davide added a subscriber: llvm-commits.

I originally started working on adding support for vectors `insertelement` and friends than I realized we could re-use the code we use for handling structs for the purpose.
So, I decided to struct support first and put the rewrite of http://reviews.llvm.org/D22186 on hold.
This patch only works for `SCCP` but it shouldn't be hard to port to the interprocedural version of this pass if we agree this is the right way of handling this case.

http://reviews.llvm.org/D22269

Files:
  lib/Transforms/Scalar/SCCP.cpp
  test/Transforms/SCCP/constant-struct.ll

Index: test/Transforms/SCCP/constant-struct.ll
===================================================================
--- /dev/null
+++ test/Transforms/SCCP/constant-struct.ll
@@ -0,0 +1,32 @@
+; Test that constant structs are folded.
+; RUN: opt %s -sccp -S | FileCheck %s
+
+define internal {i64} @struct1() {
+  %a = insertvalue {i64} undef, i64 24, 0
+  ret {i64} %a
+}
+
+; CHECK: define internal { i64 } @struct1() {
+; CHECK-NEXT:   ret { i64 } { i64 24 }
+; CHECK-NEXT: }
+
+define internal {i64, i64} @struct2() {
+  %a = insertvalue {i64, i64} undef, i64 24, 0
+  ret {i64, i64} %a
+}
+
+; CHECK: define internal { i64, i64 } @struct2() {
+; CHECK-NEXT:  ret { i64, i64 } { i64 24, i64 undef }
+; CHECK-NEXT: }
+
+define internal {i64, i64, i64} @struct3(i64 %x) {
+  %a = insertvalue {i64, i64, i64} undef, i64 24, 0
+  %b = insertvalue {i64, i64, i64} %a, i64 36, 1
+  %c = insertvalue {i64, i64, i64} %b, i64 %x, 2
+  ret {i64, i64, i64} %c
+}
+
+; CHECK: define internal { i64, i64, i64 } @struct3(i64 %x) {
+; CHECK-NEXT:  %c = insertvalue { i64, i64, i64 } { i64 24, i64 36, i64 undef }, i64 %x, 2
+; CHECK-NEXT:  ret { i64, i64, i64 } %c
+; CHECK-NEXT: }
Index: lib/Transforms/Scalar/SCCP.cpp
===================================================================
--- lib/Transforms/Scalar/SCCP.cpp
+++ lib/Transforms/Scalar/SCCP.cpp
@@ -270,6 +270,18 @@
     return BBExecutable.count(BB);
   }
 
+  std::vector<LatticeVal> getStructLatticeValueFor(Value *V) const {
+    std::vector<LatticeVal> StructValues;
+    StructType *STy = dyn_cast<StructType>(V->getType());
+    assert(STy && "getStructLatticeValueFor() can be called only on structs");
+    for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+      auto I = StructValueState.find(std::make_pair(V, i));
+      assert(I != StructValueState.end() && "Value not in valuemap!");
+      StructValues.push_back(I->second);
+    }
+    return StructValues;
+  }
+
   LatticeVal getLatticeValueFor(Value *V) const {
     DenseMap<Value*, LatticeVal>::const_iterator I = ValueState.find(V);
     assert(I != ValueState.end() && "V is not in valuemap!");
@@ -1545,16 +1557,30 @@
       if (Inst->getType()->isVoidTy() || isa<TerminatorInst>(Inst))
         continue;
 
-      // TODO: Reconstruct structs from their elements.
-      if (Inst->getType()->isStructTy())
-        continue;
-
-      LatticeVal IV = Solver.getLatticeValueFor(Inst);
-      if (IV.isOverdefined())
-        continue;
+      Constant *Const = nullptr;
+      if (Inst->getType()->isStructTy()) {
+        std::vector<LatticeVal> IVs = Solver.getStructLatticeValueFor(Inst);
+        if (std::any_of(IVs.begin(), IVs.end(),
+                        [](LatticeVal &LV) { return LV.isOverdefined(); }))
+          continue;
+        std::vector<Constant *> ConstVals;
+        StructType *ST = dyn_cast<StructType>(Inst->getType());
+        for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
+          LatticeVal V = IVs[i];
+          ConstVals.push_back(V.isConstant()
+                                  ? V.getConstant()
+                                  : UndefValue::get(ST->getElementType(i)));
+        }
+        Const = ConstantStruct::get(ST, ConstVals);
+      } else {
+        LatticeVal IV = Solver.getLatticeValueFor(Inst);
+        if (IV.isOverdefined())
+          continue;
 
-      Constant *Const = IV.isConstant()
-        ? IV.getConstant() : UndefValue::get(Inst->getType());
+        Const = IV.isConstant() ? IV.getConstant()
+                                : UndefValue::get(Inst->getType());
+      }
+      assert(Const && "Constant is nullptr here!");
       DEBUG(dbgs() << "  Constant: " << *Const << " = " << *Inst << '\n');
 
       // Replaces all of the uses of a variable with uses of the constant.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D22269.63693.patch
Type: text/x-patch
Size: 3802 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160712/ef6f304d/attachment.bin>


More information about the llvm-commits mailing list