DeadArgElim: aggregate Return assessment properly.
authorTim Northover <tnorthover@apple.com>
Wed, 11 Feb 2015 23:13:11 +0000 (23:13 +0000)
committerTim Northover <tnorthover@apple.com>
Wed, 11 Feb 2015 23:13:11 +0000 (23:13 +0000)
I mistakenly thought the liveness of each "RetVal(F, i)" depended only on F. It
actually depends on the index too, which means we need to be careful about how
the results are combined before return. In particular if a single Use returns
Live, that counts for the entire object, at the granularity we're considering.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228885 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/IPO/DeadArgumentElimination.cpp
test/Transforms/DeadArgElim/aggregates.ll

index 596204dac62b90572b5f465d3f6342aaed6abac4..44313113fce992e581e3b5eff782b07cb1cbf2aa 100644 (file)
@@ -449,12 +449,15 @@ DAE::Liveness DAE::SurveyUse(const Use *U,
         // We might be live, depending on the liveness of Use.
         return MarkIfNotLive(Use, MaybeLiveUses);
       } else {
-        DAE::Liveness Result;
+        DAE::Liveness Result = MaybeLive;
         for (unsigned i = 0; i < NumRetVals(F); ++i) {
           RetOrArg Use = CreateRet(F, i);
-          // We might be live, depending on the liveness of Use. All Results
-          // should be the same since they depend only on F.
-          Result = MarkIfNotLive(Use, MaybeLiveUses);
+          // We might be live, depending on the liveness of Use. If any
+          // sub-value is live, then the entire value is considered live. This
+          // is a conservative choice, and better tracking is possible.
+          DAE::Liveness SubResult = MarkIfNotLive(Use, MaybeLiveUses);
+          if (Result != Live)
+            Result = SubResult;
         }
         return Result;
       }
index 84370834e11e99b6c8b038e359cc9c31734bf0ea..f54c6c9ea44f8b88f4400c50188f69398711bdfb 100644 (file)
@@ -130,3 +130,33 @@ define i32 @test_ret_applies_to_all() {
   %ret = extractvalue {i32, i32} %val, 1
   ret i32 %ret
 }
+
+; Case 6: When considering @mid, the return instruciton has sub-value 0
+; unconditionally live, but 1 only conditionally live. Since at that level we're
+; applying the results to the whole of %res, this means %res is live and cannot
+; be reduced. There is scope for further optimisation here (though not visible
+; in this test-case).
+
+; CHECK-LABEL: define internal { i8*, i32 } @inner()
+
+define internal {i8*, i32} @mid() {
+  %res = call {i8*, i32} @inner()
+  %intval = extractvalue {i8*, i32} %res, 1
+  %tst = icmp eq i32 %intval, 42
+  br i1 %tst, label %true, label %true
+
+true:
+  ret {i8*, i32} %res
+}
+
+define internal {i8*, i32} @inner() {
+  ret {i8*, i32} {i8* null, i32 42}
+}
+
+define internal i8 @outer() {
+  %res = call {i8*, i32} @mid()
+  %resptr = extractvalue {i8*, i32} %res, 0
+
+  %val = load i8* %resptr
+  ret i8 %val
+}
\ No newline at end of file