[llvm] d6eb480 - [IROutliner] Ensure that phi values that are passed in as arguments are remapped as arguments

Andrew Litteken via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 14 10:16:39 PDT 2022


Author: Andrew Litteken
Date: 2022-04-14T12:16:23-05:00
New Revision: d6eb480afbc038871570fa053d772c913cd77a61

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

LOG: [IROutliner] Ensure that phi values that are passed in as arguments are remapped as arguments

Issue: https://github.com/llvm/llvm-project/issues/54430

For incoming values of phi nodes added to an outlined function to accommodate different exit paths in the function, when a value is a constant that is passed into the outlined function as an argument, we find the corresponding value in the first extracted function used to fill the overall outlined function. When this value is an argument, the corresponding value used will be the old value, prior to outlining. This patch maintains a mapping from these values to arguments, and uses this mapping to update the added phi node accordingly.

Reviewers: paquette

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

Added: 
    llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll

Modified: 
    llvm/include/llvm/Transforms/IPO/IROutliner.h
    llvm/lib/Transforms/IPO/IROutliner.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/IPO/IROutliner.h b/llvm/include/llvm/Transforms/IPO/IROutliner.h
index a75a5046f3c6b..315587e0f9228 100644
--- a/llvm/include/llvm/Transforms/IPO/IROutliner.h
+++ b/llvm/include/llvm/Transforms/IPO/IROutliner.h
@@ -85,6 +85,13 @@ struct OutlinableRegion {
   DenseMap<unsigned, unsigned> ExtractedArgToAgg;
   DenseMap<unsigned, unsigned> AggArgToExtracted;
 
+  /// Values in the outlined functions will often be replaced by arguments. When
+  /// finding corresponding values from one region to another, the found value
+  /// will be the value the argument previously replaced.  This structure maps
+  /// any replaced values for the region to the aggregate aggregate argument
+  /// in the overall function.
+  DenseMap<Value *, Value *> RemappedArguments;
+
   /// Marks whether we need to change the order of the arguments when mapping
   /// the old extracted function call to the new aggregate outlined function
   /// call.

diff  --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp
index ab6b74f9899ec..9bde8bcf9cf07 100644
--- a/llvm/lib/Transforms/IPO/IROutliner.cpp
+++ b/llvm/lib/Transforms/IPO/IROutliner.cpp
@@ -1737,6 +1737,10 @@ findOrCreatePHIInBlock(PHINode &PN, OutlinableRegion &Region,
     IncomingVal = findOutputMapping(OutputMappings, IncomingVal);
     Value *Val = Region.findCorrespondingValueIn(*FirstRegion, IncomingVal);
     assert(Val && "Value is nullptr?");
+    DenseMap<Value *, Value *>::iterator RemappedIt =
+        FirstRegion->RemappedArguments.find(Val);
+    if (RemappedIt != FirstRegion->RemappedArguments.end())
+      Val = RemappedIt->second;
     NewPN->setIncomingValue(Idx, Val);
   }
   return NewPN;
@@ -1780,6 +1784,8 @@ replaceArgumentUses(OutlinableRegion &Region,
                         << *Region.ExtractedFunction << " with " << *AggArg
                         << " in function " << *Group.OutlinedFunction << "\n");
       Arg->replaceAllUsesWith(AggArg);
+      Value *V = Region.Call->getArgOperand(ArgIdx);
+      Region.RemappedArguments.insert(std::make_pair(V, AggArg));
       continue;
     }
 

diff  --git a/llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll b/llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll
new file mode 100644
index 0000000000000..1c0b68ac40872
--- /dev/null
+++ b/llvm/test/Transforms/IROutliner/exit-phi-nodes-incoming-value-constant-argument.ll
@@ -0,0 +1,111 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs
+; RUN: opt -S -verify -iroutliner -ir-outlining-no-cost < %s | FileCheck %s
+
+; When consolidating PHINodes, the outliner replaces the incoming value with
+; a corresponding value from the first outlined section.  When this replaced
+; value is passed in as an argument, the corresponding value is found outside
+; of the outlined region, and must be replaced with an argument to avoid
+; dominating value errors. This checks that we use the argument to replace
+; the incoming value.
+
+define void @func1(i32 %0, i32 %1) local_unnamed_addr #0 {
+bb1:
+  br label %bb5s
+
+bb2:
+  %a = add i32 %0, %1
+  %b = add i32 %0, %1
+  %c = icmp eq i32 %b, %a
+  br i1 %c, label %bb5, label %bb3
+
+bb3:
+  %d = add i32 %0, %1
+  br label %bb5
+
+bb4:
+  %e = sub i32 %0, %1
+  br label %bb2
+
+bb5:
+  ret void
+}
+
+define void @func2(i32 %0, i32 %1) local_unnamed_addr #0 {
+bb1:
+  br label %bb5
+
+bb2:
+  %a = sub i32 %0, %1
+  %b = add i32 %0, %1
+  %c = icmp eq i32 %b, 1
+  br i1 %c, label %bb5, label %bb3
+
+bb3:
+  %d = add i32 %0, %1
+  br label %bb5
+
+bb4:
+  %e = add i32 %0, %1
+  br label %bb2
+
+bb5:
+  %f = phi i32 [ 0, %bb1 ], [ 1, %bb2 ], [ 1, %bb3 ]
+  ret void
+}
+; CHECK-LABEL: @func1(
+; CHECK-NEXT:  bb1:
+; CHECK-NEXT:    br label [[BB5:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[A:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT:    call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], i32 [[A]], i32* null, i32 -1)
+; CHECK-NEXT:    br label [[BB5]]
+; CHECK:       bb4:
+; CHECK-NEXT:    [[E:%.*]] = sub i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb5:
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: @func2(
+; CHECK-NEXT:  bb1:
+; CHECK-NEXT:    [[F_CE_LOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    br label [[BB5:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    [[A:%.*]] = sub i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT:    [[LT_CAST:%.*]] = bitcast i32* [[F_CE_LOC]] to i8*
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]])
+; CHECK-NEXT:    call void @outlined_ir_func_0(i32 [[TMP0]], i32 [[TMP1]], i32 1, i32* [[F_CE_LOC]], i32 0)
+; CHECK-NEXT:    [[F_CE_RELOAD:%.*]] = load i32, i32* [[F_CE_LOC]], align 4
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 -1, i8* [[LT_CAST]])
+; CHECK-NEXT:    br label [[BB5]]
+; CHECK:       bb4:
+; CHECK-NEXT:    [[E:%.*]] = add i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    br label [[BB2:%.*]]
+; CHECK:       bb5:
+; CHECK-NEXT:    [[F:%.*]] = phi i32 [ 0, [[BB1:%.*]] ], [ [[F_CE_RELOAD]], [[BB2]] ]
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define internal void @outlined_ir_func_0(
+; CHECK-NEXT:  newFuncRoot:
+; CHECK-NEXT:    br label [[BB2_TO_OUTLINE:%.*]]
+; CHECK:       bb2_to_outline:
+; CHECK-NEXT:    [[B:%.*]] = add i32 [[TMP0:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[B]], [[TMP2:%.*]]
+; CHECK-NEXT:    br i1 [[C]], label [[PHI_BLOCK:%.*]], label [[BB3:%.*]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[D:%.*]] = add i32 [[TMP0]], [[TMP1]]
+; CHECK-NEXT:    br label [[PHI_BLOCK]]
+; CHECK:       bb5.exitStub:
+; CHECK-NEXT:    switch i32 [[TMP4:%.*]], label [[FINAL_BLOCK_0:%.*]] [
+; CHECK-NEXT:    i32 0, label [[OUTPUT_BLOCK_1_0:%.*]]
+; CHECK-NEXT:    ]
+; CHECK:       output_block_1_0:
+; CHECK-NEXT:    store i32 [[TMP5:%.*]], i32* [[TMP3:%.*]], align 4
+; CHECK-NEXT:    br label [[FINAL_BLOCK_0]]
+; CHECK:       phi_block:
+; CHECK-NEXT:    [[TMP5]] = phi i32 [ [[TMP2]], [[BB2_TO_OUTLINE]] ], [ [[TMP2]], [[BB3]] ]
+; CHECK-NEXT:    br label [[BB5_EXITSTUB:%.*]]
+; CHECK:       final_block_0:
+; CHECK-NEXT:    ret void
+;


        


More information about the llvm-commits mailing list