[llvm] 00928a1 - Fix SROA with a PHI mergig values from a same block

Stanislav Mekhanoshin via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 26 12:58:41 PDT 2020


Author: Stanislav Mekhanoshin
Date: 2020-10-26T12:58:27-07:00
New Revision: 00928a1956a1618f394ffe99fc63b0d81e1f88c7

URL: https://github.com/llvm/llvm-project/commit/00928a1956a1618f394ffe99fc63b0d81e1f88c7
DIFF: https://github.com/llvm/llvm-project/commit/00928a1956a1618f394ffe99fc63b0d81e1f88c7.diff

LOG: Fix SROA with a PHI mergig values from a same block

This fixes the bug 47945. It is legal to have a PHI with values
from from the same block, but values must stay the same. In this
case it is illegal to merge different values.

Differential Revision: https://reviews.llvm.org/D89978

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/SROA.cpp
    llvm/test/Transforms/SROA/phi-gep.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index 09e30a46c167..a6fa4c734fd8 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -3545,13 +3545,20 @@ class AggLoadStoreRewriter : public InstVisitor<AggLoadStoreRewriter, bool> {
                                           PHI->getNumIncomingValues(),
                                           PHI->getName() + ".sroa.phi");
     for (unsigned I = 0, E = PHI->getNumIncomingValues(); I != E; ++I) {
-      Instruction *In = cast<Instruction>(PHI->getIncomingValue(I));
+      BasicBlock *B = PHI->getIncomingBlock(I);
+      Value *NewVal = nullptr;
+      int Idx = NewPN->getBasicBlockIndex(B);
+      if (Idx >= 0) {
+        NewVal = NewPN->getIncomingValue(Idx);
+      } else {
+        Instruction *In = cast<Instruction>(PHI->getIncomingValue(I));
 
-      IRBuilderTy B(In->getParent(), std::next(In->getIterator()));
-      Value *NewVal = IsInBounds
-          ? B.CreateInBoundsGEP(In, Index, In->getName() + ".sroa.gep")
-          : B.CreateGEP(In, Index, In->getName() + ".sroa.gep");
-      NewPN->addIncoming(NewVal, PHI->getIncomingBlock(I));
+        IRBuilderTy B(In->getParent(), std::next(In->getIterator()));
+        NewVal = IsInBounds
+            ? B.CreateInBoundsGEP(In, Index, In->getName() + ".sroa.gep")
+            : B.CreateGEP(In, Index, In->getName() + ".sroa.gep");
+      }
+      NewPN->addIncoming(NewVal, B);
     }
 
     Visited.erase(&GEPI);

diff  --git a/llvm/test/Transforms/SROA/phi-gep.ll b/llvm/test/Transforms/SROA/phi-gep.ll
index 88c354246009..6bf2a7718658 100644
--- a/llvm/test/Transforms/SROA/phi-gep.ll
+++ b/llvm/test/Transforms/SROA/phi-gep.ll
@@ -452,6 +452,75 @@ bb2:
   ret void
 }
 
+define void @constant_value_phi() {
+; CHECK-LABEL: @constant_value_phi(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LAND_LHS_TRUE_I:%.*]]
+; CHECK:       land.lhs.true.i:
+; CHECK-NEXT:    br i1 undef, label [[COND_END_I:%.*]], label [[COND_END_I]]
+; CHECK:       cond.end.i:
+; CHECK-NEXT:    unreachable
+;
+entry:
+  %s1 = alloca [3 x i16]
+  %s = alloca [3 x i16]
+  %cast = bitcast [3 x i16]* %s1 to i16*
+  br label %land.lhs.true.i
+
+land.lhs.true.i:                                  ; preds = %entry
+  br i1 undef, label %cond.end.i, label %cond.end.i
+
+cond.end.i:                                       ; preds = %land.lhs.true.i, %land.lhs.true.i
+  %.pre-phi1 = phi i16* [ %cast, %land.lhs.true.i ], [ %cast, %land.lhs.true.i ]
+  %cast2 = bitcast [3 x i16]* %s to i16*
+  call void @llvm.memcpy.p0i16.p0i16.i64(i16* %.pre-phi1, i16* %cast2, i64 3, i1 false)
+  %gep = getelementptr inbounds [3 x i16], [3 x i16]* %s, i32 0, i32 0
+  %load = load i16, i16* %gep
+  unreachable
+}
+
+define i32 @test_sroa_phi_gep_multiple_values_from_same_block(i32 %arg) {
+; CHECK-LABEL: @test_sroa_phi_gep_multiple_values_from_same_block(
+; CHECK-NEXT:  bb.1:
+; CHECK-NEXT:    switch i32 [[ARG:%.*]], label [[BB_3:%.*]] [
+; CHECK-NEXT:    i32 1, label [[BB_2:%.*]]
+; CHECK-NEXT:    i32 2, label [[BB_2]]
+; CHECK-NEXT:    i32 3, label [[BB_4:%.*]]
+; CHECK-NEXT:    i32 4, label [[BB_4]]
+; CHECK-NEXT:    ]
+; CHECK:       bb.2:
+; CHECK-NEXT:    br label [[BB_4]]
+; CHECK:       bb.3:
+; CHECK-NEXT:    br label [[BB_4]]
+; CHECK:       bb.4:
+; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[BB_3]] ], [ undef, [[BB_2]] ], [ undef, [[BB_1:%.*]] ], [ undef, [[BB_1]] ]
+; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
+;
+bb.1:
+  %a = alloca %pair, align 4
+  %b = alloca %pair, align 4
+  switch i32 %arg, label %bb.3 [
+  i32 1, label %bb.2
+  i32 2, label %bb.2
+  i32 3, label %bb.4
+  i32 4, label %bb.4
+  ]
+
+bb.2:                                                ; preds = %bb.1, %bb.1
+  br label %bb.4
+
+bb.3:                                                ; preds = %bb.1
+  br label %bb.4
+
+bb.4:                                                ; preds = %bb.1, %bb.1, %bb.3, %bb.2
+  %phi = phi %pair* [ %a, %bb.3 ], [ %a, %bb.2 ], [ %b, %bb.1 ], [ %b, %bb.1 ]
+  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
+  %load = load i32, i32* %gep, align 4
+  ret i32 %load
+}
+
 declare %pair* @foo()
 
 declare i32 @__gxx_personality_v0(...)
+
+declare void @llvm.memcpy.p0i16.p0i16.i64(i16* noalias nocapture writeonly, i16* noalias nocapture readonly, i64, i1 immarg)


        


More information about the llvm-commits mailing list