[llvm] r241950 - [SEH] Push reloads of the SEH code past phi nodes

Reid Kleckner reid at kleckner.net
Fri Jul 10 15:21:54 PDT 2015


Author: rnk
Date: Fri Jul 10 17:21:54 2015
New Revision: 241950

URL: http://llvm.org/viewvc/llvm-project?rev=241950&view=rev
Log:
[SEH] Push reloads of the SEH code past phi nodes

This in turn would sometimes introduce new cleanupblocks that didn't
previously exist. The uses were being introduced by SSA value demotion.
We actually want to *promote* uses of EH pointers and selectors, so I
added some spcecial casing to avoid demoting such instructions.  This is
getting overly complicated, but hopefully we'll come along and delete it
in the new representation.

Added:
    llvm/trunk/test/CodeGen/WinEH/seh-exception-code2.ll
Modified:
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=241950&r1=241949&r2=241950&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Fri Jul 10 17:21:54 2015
@@ -616,6 +616,26 @@ void WinEHPrepare::demoteValuesLiveAcros
   // identifyEHBlocks() should have been called before this function.
   assert(!NormalBlocks.empty());
 
+  // Try to avoid demoting EH pointer and selector values. They get in the way
+  // of our pattern matching.
+  SmallPtrSet<Instruction *, 10> EHVals;
+  for (BasicBlock &BB : F) {
+    LandingPadInst *LP = BB.getLandingPadInst();
+    if (!LP)
+      continue;
+    EHVals.insert(LP);
+    for (User *U : LP->users()) {
+      auto *EI = dyn_cast<ExtractValueInst>(U);
+      if (!EI)
+        continue;
+      EHVals.insert(EI);
+      for (User *U2 : EI->users()) {
+        if (auto *PN = dyn_cast<PHINode>(U2))
+          EHVals.insert(PN);
+      }
+    }
+  }
+
   SetVector<Argument *> ArgsToDemote;
   SetVector<Instruction *> InstrsToDemote;
   for (BasicBlock &BB : F) {
@@ -641,7 +661,11 @@ void WinEHPrepare::demoteValuesLiveAcros
           continue;
         }
 
+        // Don't demote EH values.
         auto *OpI = cast<Instruction>(Op);
+        if (EHVals.count(OpI))
+          continue;
+
         BasicBlock *OpBB = OpI->getParent();
         // If a value is produced and consumed in the same BB, we don't need to
         // demote it.
@@ -822,7 +846,8 @@ bool WinEHPrepare::prepareExceptionHandl
     LPad->replaceAllUsesWith(UndefValue::get(LPad->getType()));
 
     // Rewrite uses of the exception pointer to loads of an alloca.
-    for (Instruction *E : SEHCodeUses) {
+    while (!SEHCodeUses.empty()) {
+      Instruction *E = SEHCodeUses.pop_back_val();
       SmallVector<Use *, 4> Uses;
       for (Use &U : E->uses())
         Uses.push_back(&U);
@@ -830,13 +855,10 @@ bool WinEHPrepare::prepareExceptionHandl
         auto *I = cast<Instruction>(U->getUser());
         if (isa<ResumeInst>(I))
           continue;
-        LoadInst *LI;
         if (auto *Phi = dyn_cast<PHINode>(I))
-          LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false,
-                            Phi->getIncomingBlock(*U)->getTerminator());
+          SEHCodeUses.push_back(Phi);
         else
-          LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I);
-        U->set(LI);
+          U->set(new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I));
       }
       E->replaceAllUsesWith(UndefValue::get(E->getType()));
       E->eraseFromParent();

Added: llvm/trunk/test/CodeGen/WinEH/seh-exception-code2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/seh-exception-code2.ll?rev=241950&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/seh-exception-code2.ll (added)
+++ llvm/trunk/test/CodeGen/WinEH/seh-exception-code2.ll Fri Jul 10 17:21:54 2015
@@ -0,0 +1,91 @@
+; RUN: opt -winehprepare -S < %s | FileCheck %s
+
+; WinEHPrepare was crashing during phi demotion.
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc18.0.0"
+
+declare i32 @__C_specific_handler(...)
+
+ at str = linkonce_odr unnamed_addr constant [16 x i8] c"caught it! %lx\0A\00", align 1
+
+declare void @maycrash()
+declare void @finally(i1 %abnormal)
+declare i32 @printf(i8* nocapture readonly, ...)
+declare i32 @llvm.eh.typeid.for(i8*)
+
+; Function Attrs: nounwind uwtable
+define void @doit() personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) {
+entry:
+  invoke void @maycrash()
+          to label %invoke.cont unwind label %lpad.1
+
+invoke.cont:                                      ; preds = %entry
+  invoke void @maycrash()
+          to label %__try.cont unwind label %lpad
+
+lpad:                                             ; preds = %entry
+  %lp0 = landingpad { i8*, i32 }
+          cleanup
+          catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@doit@@" to i8*)
+  %ehptr.0 = extractvalue { i8*, i32 } %lp0, 0
+  %ehsel.0 = extractvalue { i8*, i32 } %lp0, 1
+  call void @finally(i1 true)
+  br label %ehdispatch
+
+lpad.1:                                           ; preds = %invoke.cont, %lpad
+  %lp1 = landingpad { i8*, i32 }
+          catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@doit@@" to i8*)
+  %ehptr.1 = extractvalue { i8*, i32 } %lp1, 0
+  %ehsel.1 = extractvalue { i8*, i32 } %lp1, 1
+  br label %ehdispatch
+
+ehdispatch:
+  %ehptr.2 = phi i8* [ %ehptr.0, %lpad ], [ %ehptr.1, %lpad.1 ]
+  %ehsel.2 = phi i32 [ %ehsel.0, %lpad ], [ %ehsel.1, %lpad.1 ]
+  %mysel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@doit@@" to i8*))
+  %matches = icmp eq i32 %ehsel.2, %mysel
+  br i1 %matches, label %__except, label %eh.resume
+
+__except:                                         ; preds = %lpad, %lpad.1
+  %t4 = ptrtoint i8* %ehptr.2 to i64
+  %t5 = trunc i64 %t4 to i32
+  %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @str, i64 0, i64 0), i32 %t5)
+  br label %__try.cont
+
+__try.cont:                                       ; preds = %invoke.cont, %__except
+  call void @finally(i1 false)
+  ret void
+
+eh.resume:
+  %ehvals0 = insertvalue { i8*, i32 } undef, i8* %ehptr.2, 0
+  %ehvals = insertvalue { i8*, i32 } %ehvals0, i32 %ehsel.2, 1
+  resume { i8*, i32 } %ehvals
+}
+
+define internal i32 @"\01?filt$0 at 0@doit@@"(i8* %exception_pointers, i8* %frame_pointer) #1 {
+entry:
+  %0 = bitcast i8* %exception_pointers to { i32*, i8* }*
+  %1 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %0, i32 0, i32 0
+  %2 = load i32*, i32** %1
+  %3 = load i32, i32* %2
+  %cmp = icmp eq i32 %3, -1073741819
+  %4 = zext i1 %cmp to i32
+  ret i32 %4
+}
+
+; CHECK-LABEL: define void @doit()
+; CHECK: %lp0 = landingpad { i8*, i32 }
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8*
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions({{.*}})
+; CHECK-NEXT: indirectbr i8* %{{[^,]*}}, [label %__except]
+;
+; CHECK: %lp1 = landingpad { i8*, i32 }
+; CHECK-NEXT: catch i8*
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions({{.*}})
+; CHECK-NEXT: indirectbr i8* %{{[^,]*}}, [label %__except]
+;
+; CHECK: __except:
+; CHECK: call i32 @llvm.eh.exceptioncode()
+; CHECK: call i32 (i8*, ...) @printf





More information about the llvm-commits mailing list