[llvm] r298655 - [Hexagon] Avoid infinite loops in HexagonLoopIdiomRecognition

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 23 16:01:22 PDT 2017


Author: kparzysz
Date: Thu Mar 23 18:01:22 2017
New Revision: 298655

URL: http://llvm.org/viewvc/llvm-project?rev=298655&view=rev
Log:
[Hexagon] Avoid infinite loops in HexagonLoopIdiomRecognition

- Avoid explosive growth of the simplification queue by not queuing
  expressions that are alredy in it.
- Add an iteration counter and abort after a sufficiently large number
  of iterations (assuming that it's a symptom of an infinite loop).

Added:
    llvm/trunk/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll
Modified:
    llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp

Modified: llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp?rev=298655&r1=298654&r2=298655&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp Thu Mar 23 18:01:22 2017
@@ -136,7 +136,24 @@ namespace {
     void addRule(const Rule &R) { Rules.push_back(R); }
 
   private:
-    typedef std::deque<Value*> WorkListType;
+    struct WorkListType {
+      WorkListType() = default;
+
+      void push_back(Value* V) {
+        // Do not push back duplicates.
+        if (!S.count(V)) { Q.push_back(V); S.insert(V); }
+      }
+      Value *pop_front_val() {
+        Value *V = Q.front(); Q.pop_front(); S.erase(V);
+        return V;
+      }
+      bool empty() const { return Q.empty(); }
+
+    private:
+      std::deque<Value*> Q;
+      std::set<Value*> S;
+    };
+
     typedef std::set<Value*> ValueSetType;
     std::vector<Rule> Rules;
 
@@ -199,8 +216,7 @@ void Simplifier::Context::traverse(Value
   Q.push_back(V);
 
   while (!Q.empty()) {
-    Instruction *U = dyn_cast<Instruction>(Q.front());
-    Q.pop_front();
+    Instruction *U = dyn_cast<Instruction>(Q.pop_front_val());
     if (!U || U->getParent())
       continue;
     if (!F(U))
@@ -248,8 +264,7 @@ void Simplifier::Context::initialize(Ins
   Q.push_back(Exp);
 
   while (!Q.empty()) {
-    Value *V = Q.front();
-    Q.pop_front();
+    Value *V = Q.pop_front_val();
     if (M.find(V) != M.end())
       continue;
     if (Instruction *U = dyn_cast<Instruction>(V)) {
@@ -320,8 +335,7 @@ Value *Simplifier::Context::subst(Value
   WorkListType Q;
   Q.push_back(Tree);
   while (!Q.empty()) {
-    Instruction *U = dyn_cast<Instruction>(Q.front());
-    Q.pop_front();
+    Instruction *U = dyn_cast<Instruction>(Q.pop_front_val());
     // If U is not an instruction, or it's not a clone, skip it.
     if (!U || U->getParent())
       continue;
@@ -355,8 +369,7 @@ void Simplifier::Context::replace(Value
   WorkListType Q;
   Q.push_back(NewV);
   while (!Q.empty()) {
-    Value *V = Q.front();
-    Q.pop_front();
+    Value *V = Q.pop_front_val();
     Instruction *U = dyn_cast<Instruction>(V);
     if (!U || U->getParent())
       continue;
@@ -421,8 +434,7 @@ Value *Simplifier::Context::find(Value *
   Q.push_back(Tree);
 
   while (!Q.empty()) {
-    Value *V = Q.front();
-    Q.pop_front();
+    Value *V = Q.pop_front_val();
     if (V == Sub)
       return V;
     Instruction *U = dyn_cast<Instruction>(V);
@@ -463,10 +475,13 @@ Value *Simplifier::Context::materialize(
 Value *Simplifier::simplify(Context &C) {
   WorkListType Q;
   Q.push_back(C.Root);
+  unsigned Count = 0;
+  const unsigned Limit = 100000;
 
   while (!Q.empty()) {
-    Instruction *U = dyn_cast<Instruction>(Q.front());
-    Q.pop_front();
+    if (Count++ >= Limit)
+      break;
+    Instruction *U = dyn_cast<Instruction>(Q.pop_front_val());
     if (!U || U->getParent() || !C.Used.count(U))
       continue;
     bool Changed = false;
@@ -485,6 +500,7 @@ Value *Simplifier::simplify(Context &C)
         Q.push_back(Op);
     }
   }
+  assert(Count < Limit && "Infinite loop in HLIR/simplify?");
   return C.Root;
 }
 

Added: llvm/trunk/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll?rev=298655&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll Thu Mar 23 18:01:22 2017
@@ -0,0 +1,83 @@
+; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s
+; CHECK-LABEL: define void @fred
+
+; Check that this test does not crash.
+
+target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
+target triple = "hexagon"
+
+%struct.0 = type { [120 x i16], [80 x i16], [80 x i16], [80 x i16], [80 x i16], [80 x i16], [40 x i16], [40 x i16], [40 x i16], [40 x i16], [40 x i16], [40 x i16] }
+
+define void @fred(%struct.0* %demod_state) local_unnamed_addr #0 {
+entry:
+  br label %for.body309
+
+for.body309:                                      ; preds = %for.body309, %entry
+  %max_diff.0300 = phi i16 [ %max_diff.1, %for.body309 ], [ 0, %entry ]
+  %arrayidx322.phi = phi i16* [ undef, %entry ], [ %arrayidx322.inc, %for.body309 ]
+  %arrayidx331.phi = phi i16* [ undef, %entry ], [ %arrayidx331.inc, %for.body309 ]
+  %lag.4299.apmt = phi i32 [ %inc376.apmt, %for.body309 ], [ 0, %entry ]
+  %0 = load i16, i16* %arrayidx322.phi, align 2
+  %conv323 = sext i16 %0 to i32
+  %sub324 = sub nsw i32 0, %conv323
+  %ispos258 = icmp sgt i32 %sub324, -1
+  %1 = select i1 %ispos258, i32 %sub324, i32 0
+  %add326 = add nsw i32 %1, 0
+  %2 = load i16, i16* %arrayidx331.phi, align 2
+  %conv332 = sext i16 %2 to i32
+  %sub333 = sub nsw i32 0, %conv332
+  %ispos260 = icmp sgt i32 %sub333, -1
+  %3 = select i1 %ispos260, i32 %sub333, i32 undef
+  %sub342 = sub nsw i32 0, %conv323
+  %ispos262 = icmp sgt i32 %sub342, -1
+  %4 = select i1 %ispos262, i32 %sub342, i32 undef
+  %sub351 = sub nsw i32 0, %conv332
+  %ispos264 = icmp sgt i32 %sub351, -1
+  %5 = select i1 %ispos264, i32 %sub351, i32 0
+  %sub360 = sub nsw i32 %conv323, %conv332
+  %ispos266 = icmp sgt i32 %sub360, -1
+  %6 = select i1 %ispos266, i32 %sub360, i32 0
+  %add335 = add nsw i32 %add326, %4
+  %add344 = add nsw i32 %add335, %3
+  %add353 = add i32 %add344, %5
+  %add362 = add i32 %add353, %6
+  %div363 = sdiv i32 %add362, 6
+  %conv364 = trunc i32 %div363 to i16
+  %sext268 = shl i32 %div363, 16
+  %conv369 = ashr exact i32 %sext268, 16
+  %conv370 = sext i16 %max_diff.0300 to i32
+  %cmp371 = icmp sgt i32 %conv369, %conv370
+  %max_diff.1 = select i1 %cmp371, i16 %conv364, i16 %max_diff.0300
+  %inc376.apmt = add nuw nsw i32 %lag.4299.apmt, 1
+  %exitcond331 = icmp ne i32 %inc376.apmt, 40
+  %arrayidx322.inc = getelementptr i16, i16* %arrayidx322.phi, i32 1
+  %arrayidx331.inc = getelementptr i16, i16* %arrayidx331.phi, i32 1
+  br i1 %exitcond331, label %for.body309, label %for.end377
+
+for.end377:                                       ; preds = %for.body309
+  %max_diff.1.lcssa = phi i16 [ %max_diff.1, %for.body309 ]
+  %cmp407 = icmp sgt i16 %max_diff.1.lcssa, 4
+  br label %for.body405
+
+for.body405:                                      ; preds = %if.end437, %for.end377
+  %arrayidx412 = getelementptr inbounds %struct.0, %struct.0* %demod_state, i32 0, i32 11, i32 undef
+  br i1 %cmp407, label %if.then409, label %if.end437
+
+if.then409:                                       ; preds = %for.body405
+  %arrayidx416 = getelementptr inbounds [40 x i16], [40 x i16]* null, i32 0, i32 undef
+  %7 = load i16, i16* %arrayidx416, align 2
+  %conv417 = sext i16 %7 to i32
+  %shl = shl i32 %conv417, 4
+  %mul419 = mul nsw i32 %shl, 655
+  %add420 = add nsw i32 %mul419, 0
+  br label %if.end437
+
+if.end437:                                        ; preds = %if.then409, %for.body405
+  %mul431.sink = phi i32 [ %add420, %if.then409 ], [ undef, %for.body405 ]
+  %shr432257 = lshr i32 %mul431.sink, 15
+  %conv433 = trunc i32 %shr432257 to i16
+  store i16 %conv433, i16* %arrayidx412, align 2
+  br label %for.body405
+}
+
+attributes #0 = { noinline nounwind "target-cpu"="hexagonv60" "target-features"="-hvx-double,-long-calls" }




More information about the llvm-commits mailing list