<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 6, 2015 at 11:02 AM, Sanjoy Das <span dir="ltr"><<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: sanjoy<br>
Date: Tue Jan  6 13:02:56 2015<br>
New Revision: 225282<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=225282&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=225282&view=rev</a><br>
Log:<br>
This patch teaches IndVarSimplify to add nuw and nsw to certain kinds<br>
of operations that provably don't overflow. For example, we can prove<br>
%civ.inc below does not sign-overflow. With this change,<br>
IndVarSimplify changes %civ.inc to an add nsw.<br>
<br>
  define i32 @foo(i32* %array, i32* %length_ptr, i32 %init) {<br>
   entry:<br>
    %length = load i32* %length_ptr, !range !0<br>
    %len.sub.1 = sub i32 %length, 1<br>
    %upper = icmp slt i32 %init, %len.sub.1<br>
    br i1 %upper, label %loop, label %exit<br>
<br>
   loop:<br>
    %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
    %civ.inc = add i32 %civ, 1<br>
    %cmp = icmp slt i32 %civ.inc, %length<br>
    br i1 %cmp, label %latch, label %break<br>
<br>
   latch:<br>
    store i32 0, i32* %array<br>
    %check = icmp slt i32 %civ.inc, %len.sub.1<br>
    br i1 %check, label %loop, label %break<br>
<br>
   break:<br>
    ret i32 %civ.inc<br>
<br>
   exit:<br>
    ret i32 42<br>
  }<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D6748" target="_blank">http://reviews.llvm.org/D6748</a><br>
<br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll<br>
Modified:<br>
    llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp<br>
    llvm/trunk/test/Transforms/BBVectorize/loop1.ll<br>
    llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=225282&r1=225281&r2=225282&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=225282&r1=225281&r2=225282&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Tue Jan  6 13:02:56 2015<br>
@@ -80,6 +80,7 @@ namespace {<br>
     void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);<br>
     void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand,<br>
                               bool IsSigned);<br>
+    bool strengthenOverflowingOperation(BinaryOperator *OBO, Value *IVOperand);<br>
<br>
     Instruction *splitOverflowIntrinsic(Instruction *IVUser,<br>
                                         const DominatorTree *DT);<br>
@@ -271,6 +272,120 @@ bool SimplifyIndvar::eliminateIVUser(Ins<br>
   return true;<br>
 }<br>
<br>
+/// Annotate BO with nsw / nuw if it provably does not signed-overflow /<br>
+/// unsigned-overflow.  Returns true if anything changed, false otherwise.<br>
+bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,<br>
+                                                    Value *IVOperand) {<br>
+<br>
+  // Currently we only handle instructions of the form "add <indvar> <value>"<br>
+  // and "sub <indvar> <value>".<br>
+  unsigned Op = BO->getOpcode();<br>
+  if (!(Op == Instruction::Add || Op == Instruction::Sub))<br>
+    return false;<br>
+<br>
+  // If BO is already both nuw and nsw then there is nothing left to do<br>
+  if (BO->hasNoUnsignedWrap() && BO->hasNoSignedWrap())<br>
+    return false;<br>
+<br>
+  IntegerType *IT = cast<IntegerType>(IVOperand->getType());<br>
+  Value *OtherOperand = nullptr;<br>
+  int OtherOperandIdx = -1;<br>
+  if (BO->getOperand(0) == IVOperand) {<br>
+    OtherOperand = BO->getOperand(1);<br>
+    OtherOperandIdx = 1;<br>
+  } else {<br>
+    assert(BO->getOperand(1) == IVOperand && "only other use!");<br>
+    OtherOperand = BO->getOperand(0);<br>
+    OtherOperandIdx = 0;<br>
+  }<br>
+<br>
+  bool Changed = false;<br>
+  const SCEV *OtherOpSCEV = SE->getSCEV(OtherOperand);<br>
+  if (OtherOpSCEV == SE->getCouldNotCompute())<br>
+    return false;<br>
+<br>
+  if (Op == Instruction::Sub) {<br>
+    // If the subtraction is of the form "sub <indvar>, <op>", then pretend it<br>
+    // is "add <indvar>, -<op>" and continue, else bail out.<br>
+    if (OtherOperandIdx != 1)<br>
+      return false;<br>
+<br>
+    OtherOpSCEV = SE->getNegativeSCEV(OtherOpSCEV);<br>
+  }<br>
+<br>
+  const SCEV *IVOpSCEV = SE->getSCEV(IVOperand);<br>
+  const SCEV *ZeroSCEV = SE->getConstant(IVOpSCEV->getType(), 0);<br>
+<br>
+  if (!BO->hasNoSignedWrap()) {<br>
+    // Upgrade the add to an "add nsw" if we can prove that it will never<br>
+    // sign-overflow or sign-underflow.<br>
+<br>
+    const SCEV *SignedMax =<br>
+      SE->getConstant(APInt::getSignedMaxValue(IT->getBitWidth()));<br>
+    const SCEV *SignedMin =<br>
+      SE->getConstant(APInt::getSignedMinValue(IT->getBitWidth()));<br>
+<br>
+    // The addition "IVOperand + OtherOp" does not sign-overflow if the result<br>
+    // is sign-representable in 2's complement in the given bit-width.<br>
+    //<br>
+    // If OtherOp is SLT 0, then for an IVOperand in [SignedMin - OtherOp,<br>
+    // SignedMax], "IVOperand + OtherOp" is in [SignedMin, SignedMax + OtherOp].<br>
+    // Everything in [SignedMin, SignedMax + OtherOp] is representable since<br>
+    // SignedMax + OtherOp is at least -1.<br>
+    //<br>
+    // If OtherOp is SGE 0, then for an IVOperand in [SignedMin, SignedMax -<br>
+    // OtherOp], "IVOperand + OtherOp" is in [SignedMin + OtherOp, SignedMax].<br>
+    // Everything in [SignedMin + OtherOp, SignedMax] is representable since<br>
+    // SignedMin + OtherOp is at most -1.<br>
+    //<br>
+    // It follows that for all values of IVOperand in [SignedMin - smin(0,<br>
+    // OtherOp), SignedMax - smax(0, OtherOp)] the result of the add is<br>
+    // representable (i.e. there is no sign-overflow).<br>
+<br>
+    const SCEV *UpperDelta = SE->getSMaxExpr(ZeroSCEV, OtherOpSCEV);<br>
+    const SCEV *UpperLimit = SE->getMinusSCEV(SignedMax, UpperDelta);<br>
+<br>
+    bool NeverSignedOverflows =<br>
+      SE->isKnownPredicate(ICmpInst::ICMP_SLE, IVOpSCEV, UpperLimit);<br>
+<br>
+    if (NeverSignedOverflows) {<br>
+      const SCEV *LowerDelta = SE->getSMinExpr(ZeroSCEV, OtherOpSCEV);<br>
+      const SCEV *LowerLimit = SE->getMinusSCEV(SignedMin, LowerDelta);<br>
+<br>
+      bool NeverSignedUnderflows =<br>
+        SE->isKnownPredicate(ICmpInst::ICMP_SGE, IVOpSCEV, LowerLimit);<br>
+      if (NeverSignedUnderflows) {<br>
+        BO->setHasNoSignedWrap(true);<br>
+        Changed = true;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  if (!BO->hasNoUnsignedWrap()) {<br>
+    // Upgrade the add computing "IVOperand + OtherOp" to an "add nuw" if we can<br>
+    // prove that it will never unsigned-overflow (i.e. the result will always<br>
+    // be representable in the given bit-width).<br>
+    //<br>
+    // "IVOperand + OtherOp" is unsigned-representable in 2's complement iff it<br>
+    // does not produce a carry.  "IVOperand + OtherOp" produces no carry iff<br>
+    // IVOperand ULE (UnsignedMax - OtherOp).<br>
+<br>
+    const SCEV *UnsignedMax =<br>
+      SE->getConstant(APInt::getMaxValue(IT->getBitWidth()));<br>
+    const SCEV *UpperLimit = SE->getMinusSCEV(UnsignedMax, OtherOpSCEV);<br>
+<br>
+    bool NeverUnsignedOverflows =<br>
+        SE->isKnownPredicate(ICmpInst::ICMP_ULE, IVOpSCEV, UpperLimit);<br>
+<br>
+    if (NeverUnsignedOverflows) {<br>
+      BO->setHasNoUnsignedWrap(true);<br>
+      Changed = true;<br>
+    }<br>
+  }<br>
+<br>
+  return Changed;<br>
+}<br>
+<br>
 /// \brief Split sadd.with.overflow into add + sadd.with.overflow to allow<br>
 /// analysis and optimization.<br>
 ///<br>
@@ -430,6 +545,16 @@ void SimplifyIndvar::simplifyUsers(PHINo<br>
       pushIVUsers(IVOperand, Simplified, SimpleIVUsers);<br>
       continue;<br>
     }<br>
+<br>
+    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(UseOper.first)) {<br>
+      if (isa<OverflowingBinaryOperator>(BO) &&<br>
+          strengthenOverflowingOperation(BO, IVOperand)) {<br></blockquote><div><br></div><div><div>Any reason why you don't just do:</div><div>if (const auto *OBO = dyn_cast<OverflowingBinaryOperator>(BO))</div></div><div>  if (strengthenOverflowingOperation(OBO, IVOperand))</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+        // re-queue uses of the now modified binary operator and fall<br>
+        // through to the checks that remain.<br>
+        pushIVUsers(IVOperand, Simplified, SimpleIVUsers);<br>
+      }<br>
+    }<br>
+<br>
     CastInst *Cast = dyn_cast<CastInst>(UseOper.first);<br>
     if (V && Cast) {<br>
       V->visitCast(Cast);<br>
<br>
Modified: llvm/trunk/test/Transforms/BBVectorize/loop1.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BBVectorize/loop1.ll?rev=225282&r1=225281&r2=225282&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/BBVectorize/loop1.ll?rev=225282&r1=225281&r2=225282&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/BBVectorize/loop1.ll (original)<br>
+++ llvm/trunk/test/Transforms/BBVectorize/loop1.ll Tue Jan  6 13:02:56 2015<br>
@@ -83,7 +83,7 @@ for.body:<br>
 ; CHECK-UNRL: %add12 = fadd <2 x double> %add7, %mul11<br>
 ; CHECK-UNRL: %4 = bitcast double* %arrayidx14 to <2 x double>*<br>
 ; CHECK-UNRL: store <2 x double> %add12, <2 x double>* %4, align 8<br>
-; CHECK-UNRL: %indvars.iv.next.1 = add i64 %indvars.iv, 2<br>
+; CHECK-UNRL: %indvars.iv.next.1 = add nsw i64 %indvars.iv, 2<br>
 ; CHECK-UNRL: %lftr.wideiv.1 = trunc i64 %indvars.iv.next.1 to i32<br>
 ; CHECK-UNRL: %exitcond.1 = icmp eq i32 %lftr.wideiv.1, 10<br>
 ; CHECK-UNRL: br i1 %exitcond.1, label %for.end, label %for.body<br>
<br>
Modified: llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll?rev=225282&r1=225281&r2=225282&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll?rev=225282&r1=225281&r2=225282&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll (original)<br>
+++ llvm/trunk/test/Transforms/IndVarSimplify/2011-09-10-widen-nsw.ll Tue Jan  6 13:02:56 2015<br>
@@ -17,7 +17,7 @@ for.body11:<br>
 for.body153:                                      ; preds = %for.body153, %for.body11<br>
   br i1 undef, label %for.body170, label %for.body153<br>
<br>
-; CHECK: add nsw i64 %indvars.iv, 1<br>
+; CHECK: add nuw nsw i64 %indvars.iv, 1<br>
 ; CHECK: sub nsw i64 %indvars.iv, 2<br>
 ; CHECK: sub nsw i64 4, %indvars.iv<br>
 ; CHECK: mul nsw i64 %indvars.iv, 8<br>
<br>
Added: llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll?rev=225282&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll?rev=225282&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll (added)<br>
+++ llvm/trunk/test/Transforms/IndVarSimplify/strengthen-overflow.ll Tue Jan  6 13:02:56 2015<br>
@@ -0,0 +1,214 @@<br>
+; RUN: opt < %s -indvars -S | FileCheck %s<br>
+<br>
+define i32 @test.signed.add.0(i32* %array, i32 %length, i32 %init) {<br>
+; CHECK-LABEL: @test.signed.add.0<br>
+ entry:<br>
+  %upper = icmp slt i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = add i32 %civ, 1<br>
+; CHECK: %civ.inc = add nsw i32 %civ, 1<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp slt i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+define i32 @test.signed.add.1(i32* %array, i32 %length, i32 %init) {<br>
+; CHECK-LABEL: @test.signed.add.1<br>
+ entry:<br>
+  %upper = icmp sle i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = add i32 %civ, 1<br>
+; CHECK: %civ.inc = add i32 %civ, 1<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp slt i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+define i32 @test.signed.sub.0(i32* %array, i32 %length, i32 %init) {<br>
+; CHECK-LABEL: @test.signed.sub.0<br>
+ entry:<br>
+  %upper = icmp sgt i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = sub i32 %civ, 1<br>
+; CHECK: %civ.inc = sub nsw i32 %civ, 1<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp sgt i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+define i32 @test.signed.sub.1(i32* %array, i32 %length, i32 %init) {<br>
+; CHECK-LABEL: @test.signed.sub.1<br>
+ entry:<br>
+  %upper = icmp sgt i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = sub i32 %civ, 1<br>
+; CHECK: %civ.inc = sub i32 %civ, 1<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp sge i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+define i32 @test.unsigned.add.0(i32* %array, i32 %length, i32 %init) {<br>
+; CHECK-LABEL: @test.unsigned.add.0<br>
+ entry:<br>
+  %upper = icmp ult i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = add i32 %civ, 1<br>
+; CHECK: %civ.inc = add nuw i32 %civ, 1<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp ult i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+define i32 @test.unsigned.add.1(i32* %array, i32 %length, i32 %init) {<br>
+; CHECK-LABEL: @test.unsigned.add.1<br>
+ entry:<br>
+  %upper = icmp ule i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = add i32 %civ, 1<br>
+; CHECK: %civ.inc = add i32 %civ, 1<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp ult i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+define i32 @test.unsigned.sub.0(i32* %array, i32* %length_ptr, i32 %init) {<br>
+; CHECK-LABEL: @test.unsigned.sub.0<br>
+ entry:<br>
+  %length = load i32* %length_ptr, !range !0<br>
+  %upper = icmp ult i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = sub i32 %civ, 2<br>
+; CHECK: %civ.inc = sub nuw i32 %civ, 2<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp ult i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+define i32 @test.unsigned.sub.1(i32* %array, i32* %length_ptr, i32 %init) {<br>
+; CHECK-LABEL: @test.unsigned.sub.1<br>
+ entry:<br>
+  %length = load i32* %length_ptr, !range !1<br>
+  %upper = icmp ult i32 %init, %length<br>
+  br i1 %upper, label %loop, label %exit<br>
+<br>
+ loop:<br>
+; CHECK-LABEL: loop<br>
+  %civ = phi i32 [ %init, %entry ], [ %civ.inc, %latch ]<br>
+  %civ.inc = sub i32 %civ, 2<br>
+; CHECK: %civ.inc = sub i32 %civ, 2<br>
+  %cmp = icmp slt i32 %civ.inc, %length<br>
+  br i1 %cmp, label %latch, label %break<br>
+<br>
+ latch:<br>
+  store i32 0, i32* %array<br>
+  %check = icmp ult i32 %civ.inc, %length<br>
+  br i1 %check, label %loop, label %break<br>
+<br>
+ break:<br>
+  ret i32 %civ.inc<br>
+<br>
+ exit:<br>
+  ret i32 42<br>
+}<br>
+<br>
+!0 = !{i32 0, i32 2}<br>
+!1 = !{i32 0, i32 42}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>