From 5d659bdc94338f53797cc0ad34e2a77c2bfb3e66 Mon Sep 17 00:00:00 2001 From: Zoe Carver Date: Thu, 15 Oct 2020 19:08:32 -0700 Subject: [PATCH] Move insert point after PHI nodes. (#794) If replacing a PHI node with another instruction, make sure the insertion point is after the last PHI node in that block. This prevents the assertion described in #779. --- lib/Codegen/Codegen.cpp | 11 ++++++++ test/Pass/insert-after-phis.ll | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 test/Pass/insert-after-phis.ll diff --git a/lib/Codegen/Codegen.cpp b/lib/Codegen/Codegen.cpp index 920631457..75fa3e52f 100644 --- a/lib/Codegen/Codegen.cpp +++ b/lib/Codegen/Codegen.cpp @@ -99,6 +99,17 @@ llvm::Value *Codegen::getValue(Inst *I) { if (!V0) return nullptr; + // PHI nodes must be the first instructions in a basic block. If we're + // replacing a PHI node with another instruction, make sure it comes after the + // other PHI nodes. + if (ReplacedInst && + isa(ReplacedInst->getNextNode())) { + Instruction *InsertPoint = ReplacedInst; + while (isa(InsertPoint)) + InsertPoint = InsertPoint->getNextNode(); + Builder.SetInsertPoint(InsertPoint->getNextNode()); + } + switch (Ops.size()) { case 1: { switch (I->K) { diff --git a/test/Pass/insert-after-phis.ll b/test/Pass/insert-after-phis.ll new file mode 100644 index 000000000..33dd6ed7f --- /dev/null +++ b/test/Pass/insert-after-phis.ll @@ -0,0 +1,46 @@ +; RUN: %opt -load %pass -souper -S -stats -o - %s 2>&1 | %FileCheck %s + +; The main thing being tested here is just that the verifier doesn't error +; because a PHI node comes after another instruction. + +@c = local_unnamed_addr global i32 0, align 4 +@d = local_unnamed_addr global i32 0, align 4 +@e = local_unnamed_addr global i64 0, align 8 +@b = local_unnamed_addr global i32 0, align 4 +@a = global [1 x i32] zeroinitializer, align 4 +@f = global [1 x i32] zeroinitializer, align 4 + +; CHECK: define void @g() +define void @g() { +entry: + br i1 icmp ule (i32* getelementptr inbounds ([1 x i32], [1 x i32]* @a, i64 0, i64 0), i32* inttoptr (i64 6 to i32*)), label %for.body.lr.ph, label %for.end14 + +for.body.lr.ph: + %b.promoted = load i32, i32* @b, align 4 + %e.promoted = load i64, i64* @e, align 8 + br label %for.inc10 + +for.inc10: + %0 = sub nuw nsw i32 1, %b.promoted + %cmp = icmp sge i32 %b.promoted, 0 + br i1 %cmp, label %for.inc10, label %for.inc13 + +for.inc13: + %.lcssa = phi i32 [ %0, %for.inc10 ] + %dec.6.lcssa = phi i64 [ %e.promoted, %for.inc10 ] + %inc = add nsw i32 %b.promoted, 1 + br i1 icmp ule (i32* getelementptr inbounds ([1 x i32], [1 x i32]* @a, i64 0, i64 0), i32* inttoptr (i64 6 to i32*)), label %for.inc10, label %for.cond.for.end14_crit_edge + +for.cond.for.end14_crit_edge: + %.lcssa.lcssa = phi i32 [ %.lcssa, %for.inc13 ] + %dec.6.lcssa.lcssa = phi i64 [ %dec.6.lcssa, %for.inc13 ] + %inc.lcssa = phi i32 [ %inc, %for.inc13 ] + store i64 %dec.6.lcssa.lcssa, i64* @e, align 8 + br label %for.end14 + +for.end14: + ret void +} + +; CHECK: - Number of insts removed +