<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">+new llvm list<br class=""><div><blockquote type="cite" class=""><div class="">On Aug 14, 2015, at 6:33 PM, Quentin Colombet <<a href="mailto:qcolombet@apple.com" class="">qcolombet@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hi Hal,</div><div class=""><br class=""></div>Sorry to come back to this old commit, but I believe it miscompiles some code:<div class=""><a href="https://llvm.org/bugs/show_bug.cgi?id=24468" class="">https://llvm.org/bugs/show_bug.cgi?id=24468</a></div><div class=""><br class=""></div><div class="">Could you advice on a proper fix or revert?</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">-Quentin<br class=""><div class=""><blockquote type="cite" class=""><div class="">On Nov 13, 2014, at 1:16 AM, Hal Finkel <<a href="mailto:hfinkel@anl.gov" class="">hfinkel@anl.gov</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">Author: hfinkel<br class="">Date: Thu Nov 13 03:16:54 2014<br class="">New Revision: 221876<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=221876&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=221876&view=rev</a><br class="">Log:<br class="">Revert r219432 - "Revert "[BasicAA] Revert "Revert r218714 - Make better use of zext and sign information."""<br class=""><br class="">Let's try this again...<br class=""><br class="">This reverts r219432, plus a bug fix.<br class=""><br class="">Description of the bug in r219432 (by Nick):<br class=""><br class="">The bug was using AllPositive to break out of the loop; if the loop break<br class="">condition i != e is changed to i != e && AllPositive then the<br class="">test_modulo_analysis_with_global test I've added will fail as the Modulo will<br class="">be calculated incorrectly (as the last loop iteration is skipped, so Modulo<br class="">isn't updated with its Scale).<br class=""><br class="">Nick also adds this comment:<br class=""><br class="">ComputeSignBit is safe to use in loops as it takes into account phi nodes, and<br class="">the  == EK_ZeroEx check is safe in loops as, no matter how the variable changes<br class="">between iterations, zero-extensions will always guarantee a zero sign bit. The<br class="">isValueEqualInPotentialCycles check is therefore definitely not needed as all<br class="">the variable analysis holds no matter how the variables change between loop<br class="">iterations.<br class=""><br class="">And this patch also adds another enhancement to GetLinearExpression - basically<br class="">to convert ConstantInts to Offsets (see test_const_eval and<br class="">test_const_eval_scaled for the situations this improves).<br class=""><br class="">Original commit message:<br class=""><br class="">This reverts r218944, which reverted r218714, plus a bug fix.<br class=""><br class="">Description of the bug in r218714 (by Nick):<br class=""><br class="">The original patch forgot to check if the Scale in VariableGEPIndex flipped the<br class="">sign of the variable. The BasicAA pass iterates over the instructions in the<br class="">order they appear in the function, and so BasicAliasAnalysis::aliasGEP is<br class="">called with the variable it first comes across as parameter GEP1. Adding a<br class="">%reorder label puts the definition of %a after %b so aliasGEP is called with %b<br class="">as the first parameter and %a as the second. aliasGEP later calculates that %a<br class="">== %b + 1 - %idxprom where %idxprom >= 0 (if %a was passed as the first<br class="">parameter it would calculate %b == %a - 1 + %idxprom where %idxprom >= 0) -<br class="">ignoring that %idxprom is scaled by -1 here lead the patch to incorrectly<br class="">conclude that %a > %b.<br class=""><br class="">Revised patch by Nick White, thanks! Thanks to Lang to isolating the bug.<br class="">Slightly modified by me to add an early exit from the loop and avoid<br class="">unnecessary, but expensive, function calls.<br class=""><br class="">Original commit message:<br class=""><br class="">Two related things:<br class=""><br class=""> 1. Fixes a bug when calculating the offset in GetLinearExpression. The code<br class="">    previously used zext to extend the offset, so negative offsets were converted<br class="">    to large positive ones.<br class=""><br class=""> 2. Enhance aliasGEP to deduce that, if the difference between two GEP<br class="">    allocations is positive and all the variables that govern the offset are also<br class="">    positive (i.e. the offset is strictly after the higher base pointer), then<br class="">    locations that fit in the gap between the two base pointers are NoAlias.<br class=""><br class="">Patch by Nick White!<br class=""><br class="">Added:<br class="">    llvm/trunk/test/Analysis/BasicAA/zext.ll<br class="">Modified:<br class="">    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp<br class="">    llvm/trunk/test/Analysis/BasicAA/phi-aa.ll<br class=""><br class="">Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=221876&r1=221875&r2=221876&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=221876&r1=221875&r2=221876&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)<br class="">+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Thu Nov 13 03:16:54 2014<br class="">@@ -207,6 +207,14 @@ static Value *GetLinearExpression(Value<br class="">     return V;<br class="">   }<br class=""><br class="">+  if (ConstantInt *Const = dyn_cast<ConstantInt>(V)) {<br class="">+    // if it's a constant, just convert it to an offset<br class="">+    // and remove the variable.<br class="">+    Offset += Const->getValue();<br class="">+    assert(Scale == 0 && "Constant values don't have a scale");<br class="">+    return V;<br class="">+  }<br class="">+<br class="">   if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(V)) {<br class="">     if (ConstantInt *RHSC = dyn_cast<ConstantInt>(BOp->getOperand(1))) {<br class="">       switch (BOp->getOpcode()) {<br class="">@@ -254,7 +262,10 @@ static Value *GetLinearExpression(Value<br class="">     Value *Result = GetLinearExpression(CastOp, Scale, Offset, Extension,<br class="">                                         DL, Depth+1, AT, DT);<br class="">     Scale = Scale.zext(OldWidth);<br class="">-    Offset = Offset.zext(OldWidth);<br class="">+<br class="">+    // We have to sign-extend even if Extension == EK_ZeroExt as we can't<br class="">+    // decompose a sign extension (i.e. zext(x - 1) != zext(x) - zext(-1)).<br class="">+    Offset = Offset.sext(OldWidth);<br class=""><br class="">     return Result;<br class="">   }<br class="">@@ -1051,12 +1062,45 @@ BasicAliasAnalysis::aliasGEP(const GEPOp<br class="">     }<br class="">   }<br class=""><br class="">-  // Try to distinguish something like &A[i][1] against &A[42][0].<br class="">-  // Grab the least significant bit set in any of the scales.<br class="">   if (!GEP1VariableIndices.empty()) {<br class="">     uint64_t Modulo = 0;<br class="">-    for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i)<br class="">-      Modulo |= (uint64_t)GEP1VariableIndices[i].Scale;<br class="">+    bool AllPositive = true;<br class="">+    for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i) {<br class="">+<br class="">+      // Try to distinguish something like &A[i][1] against &A[42][0].<br class="">+      // Grab the least significant bit set in any of the scales. We<br class="">+      // don't need std::abs here (even if the scale's negative) as we'll<br class="">+      // be ^'ing Modulo with itself later.<br class="">+      Modulo |= (uint64_t) GEP1VariableIndices[i].Scale;<br class="">+<br class="">+      if (AllPositive) {<br class="">+        // If the Value could change between cycles, then any reasoning about<br class="">+        // the Value this cycle may not hold in the next cycle. We'll just<br class="">+        // give up if we can't determine conditions that hold for every cycle:<br class="">+        const Value *V = GEP1VariableIndices[i].V;<br class="">+<br class="">+        bool SignKnownZero, SignKnownOne;<br class="">+        ComputeSignBit(<br class="">+          const_cast<Value *>(V),<br class="">+          SignKnownZero, SignKnownOne,<br class="">+          DL, 0, AT, nullptr, DT);<br class="">+<br class="">+        // Zero-extension widens the variable, and so forces the sign<br class="">+        // bit to zero.<br class="">+        bool IsZExt = GEP1VariableIndices[i].Extension == EK_ZeroExt;<br class="">+        SignKnownZero |= IsZExt;<br class="">+        SignKnownOne &= !IsZExt;<br class="">+<br class="">+        // If the variable begins with a zero then we know it's<br class="">+        // positive, regardless of whether the value is signed or<br class="">+        // unsigned.<br class="">+        int64_t Scale = GEP1VariableIndices[i].Scale;<br class="">+        AllPositive =<br class="">+          (SignKnownZero && Scale >= 0) ||<br class="">+          (SignKnownOne && Scale < 0);<br class="">+      }<br class="">+    }<br class="">+<br class="">     Modulo = Modulo ^ (Modulo & (Modulo - 1));<br class=""><br class="">     // We can compute the difference between the two addresses<br class="">@@ -1066,6 +1110,12 @@ BasicAliasAnalysis::aliasGEP(const GEPOp<br class="">     if (V1Size != UnknownSize && V2Size != UnknownSize &&<br class="">         ModOffset >= V2Size && V1Size <= Modulo - ModOffset)<br class="">       return NoAlias;<br class="">+<br class="">+    // If we know all the variables are positive, then GEP1 >= GEP1BasePtr.<br class="">+    // If GEP1BasePtr > V2 (GEP1BaseOffset > 0) then we know the pointers<br class="">+    // don't alias if V2Size can fit in the gap between V2 and GEP1BasePtr.<br class="">+    if (AllPositive && GEP1BaseOffset > 0 && V2Size <= (uint64_t) GEP1BaseOffset)<br class="">+      return NoAlias;<br class="">   }<br class=""><br class="">   // Statically, we can see that the base objects are the same, but the<br class=""><br class="">Modified: llvm/trunk/test/Analysis/BasicAA/phi-aa.ll<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/phi-aa.ll?rev=221876&r1=221875&r2=221876&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/phi-aa.ll?rev=221876&r1=221875&r2=221876&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/test/Analysis/BasicAA/phi-aa.ll (original)<br class="">+++ llvm/trunk/test/Analysis/BasicAA/phi-aa.ll Thu Nov 13 03:16:54 2014<br class="">@@ -39,6 +39,7 @@ return:<br class=""><br class=""> ; CHECK-LABEL: pr18068<br class=""> ; CHECK: MayAlias: i32* %0, i32* %arrayidx5<br class="">+; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5<br class=""><br class=""> define i32 @pr18068(i32* %jj7, i32* %j) {<br class=""> entry:<br class=""><br class="">Added: llvm/trunk/test/Analysis/BasicAA/zext.ll<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/zext.ll?rev=221876&view=auto" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/zext.ll?rev=221876&view=auto</a><br class="">==============================================================================<br class="">--- llvm/trunk/test/Analysis/BasicAA/zext.ll (added)<br class="">+++ llvm/trunk/test/Analysis/BasicAA/zext.ll Thu Nov 13 03:16:54 2014<br class="">@@ -0,0 +1,209 @@<br class="">+; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s<br class="">+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"<br class="">+target triple = "x86_64-unknown-linux-gnu"<br class="">+<br class="">+; CHECK-LABEL: test_with_zext<br class="">+; CHECK:  NoAlias: i8* %a, i8* %b<br class="">+<br class="">+define void @test_with_zext() {<br class="">+  %1 = tail call i8* @malloc(i64 120)<br class="">+  %a = getelementptr inbounds i8* %1, i64 8<br class="">+  %2 = getelementptr inbounds i8* %1, i64 16<br class="">+  %3 = zext i32 3 to i64<br class="">+  %b = getelementptr inbounds i8* %2, i64 %3<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_with_lshr<br class="">+; CHECK:  NoAlias: i8* %a, i8* %b<br class="">+<br class="">+define void @test_with_lshr(i64 %i) {<br class="">+  %1 = tail call i8* @malloc(i64 120)<br class="">+  %a = getelementptr inbounds i8* %1, i64 8<br class="">+  %2 = getelementptr inbounds i8* %1, i64 16<br class="">+  %3 = lshr i64 %i, 2<br class="">+  %b = getelementptr inbounds i8* %2, i64 %3<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_with_a_loop<br class="">+; CHECK:  NoAlias: i8* %a, i8* %b<br class="">+<br class="">+define void @test_with_a_loop(i8* %mem) {<br class="">+  br label %for.loop<br class="">+<br class="">+for.loop:<br class="">+  %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]<br class="">+  %a = getelementptr inbounds i8* %mem, i64 8<br class="">+  %a.plus1 = getelementptr inbounds i8* %mem, i64 16<br class="">+  %i.64 = zext i32 %i to i64<br class="">+  %b = getelementptr inbounds i8* %a.plus1, i64 %i.64<br class="">+  %i.plus1 = add nuw nsw i32 %i, 1<br class="">+  %cmp = icmp eq i32 %i.plus1, 10<br class="">+  br i1 %cmp, label %for.loop.exit, label %for.loop<br class="">+<br class="">+for.loop.exit:<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_with_varying_base_pointer_in_loop<br class="">+; CHECK:  NoAlias: i8* %a, i8* %b<br class="">+<br class="">+define void @test_with_varying_base_pointer_in_loop(i8* %mem.orig) {<br class="">+  br label %for.loop<br class="">+<br class="">+for.loop:<br class="">+  %mem = phi i8* [ %mem.orig, %0 ], [ %mem.plus1, %for.loop ]<br class="">+  %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]<br class="">+  %a = getelementptr inbounds i8* %mem, i64 8<br class="">+  %a.plus1 = getelementptr inbounds i8* %mem, i64 16<br class="">+  %i.64 = zext i32 %i to i64<br class="">+  %b = getelementptr inbounds i8* %a.plus1, i64 %i.64<br class="">+  %i.plus1 = add nuw nsw i32 %i, 1<br class="">+  %mem.plus1 = getelementptr inbounds i8* %mem, i64 8<br class="">+  %cmp = icmp eq i32 %i.plus1, 10<br class="">+  br i1 %cmp, label %for.loop.exit, label %for.loop<br class="">+<br class="">+for.loop.exit:<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_sign_extension<br class="">+; CHECK:  PartialAlias: i64* %b.i64, i8* %a<br class="">+<br class="">+define void @test_sign_extension(i32 %p) {<br class="">+  %1 = tail call i8* @malloc(i64 120)<br class="">+  %p.64 = zext i32 %p to i64<br class="">+  %a = getelementptr inbounds i8* %1, i64 %p.64<br class="">+  %p.minus1 = add i32 %p, -1<br class="">+  %p.minus1.64 = zext i32 %p.minus1 to i64<br class="">+  %b.i8 = getelementptr inbounds i8* %1, i64 %p.minus1.64<br class="">+  %b.i64 = bitcast i8* %b.i8 to i64*<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_fe_tools<br class="">+; CHECK:  PartialAlias: i32* %a, i32* %b<br class="">+<br class="">+define void @test_fe_tools([8 x i32]* %values) {<br class="">+  br label %reorder<br class="">+<br class="">+for.loop:<br class="">+  %i = phi i32 [ 0, %reorder ], [ %i.next, %for.loop ]<br class="">+  %idxprom = zext i32 %i to i64<br class="">+  %b = getelementptr inbounds [8 x i32]* %values, i64 0, i64 %idxprom<br class="">+  %i.next = add nuw nsw i32 %i, 1<br class="">+  %1 = icmp eq i32 %i.next, 10<br class="">+  br i1 %1, label %for.loop.exit, label %for.loop<br class="">+<br class="">+reorder:<br class="">+  %a = getelementptr inbounds [8 x i32]* %values, i64 0, i64 1<br class="">+  br label %for.loop<br class="">+<br class="">+for.loop.exit:<br class="">+  ret void<br class="">+}<br class="">+<br class="">+@b = global i32 0, align 4<br class="">+@d = global i32 0, align 4<br class="">+<br class="">+; CHECK-LABEL: test_spec2006<br class="">+; CHECK:  PartialAlias: i32** %x, i32** %y<br class="">+<br class="">+define void @test_spec2006() {<br class="">+  %h = alloca [1 x [2 x i32*]], align 16<br class="">+  %d.val = load i32* @d, align 4<br class="">+  %d.promoted = sext i32 %d.val to i64<br class="">+  %1 = icmp slt i32 %d.val, 2<br class="">+  br i1 %1, label %.lr.ph, label %3<br class="">+<br class="">+.lr.ph:                                           ; preds = %0<br class="">+  br label %2<br class="">+<br class="">+; <label>:2                                       ; preds = %.lr.ph, %2<br class="">+  %i = phi i32 [ %d.val, %.lr.ph ], [ %i.plus1, %2 ]<br class="">+  %i.promoted = sext i32 %i to i64<br class="">+  %x = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 %d.promoted, i64 %i.promoted<br class="">+  %i.plus1 = add nsw i32 %i, 1<br class="">+  %cmp = icmp slt i32 %i.plus1, 2<br class="">+  br i1 %cmp, label %2, label %3<br class="">+<br class="">+; <label>:3                                      ; preds = %._crit_edge, %0<br class="">+  %y = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_modulo_analysis_easy_case<br class="">+; CHECK:  NoAlias: i32** %x, i32** %y<br class="">+<br class="">+define void @test_modulo_analysis_easy_case(i64 %i) {<br class="">+  %h = alloca [1 x [2 x i32*]], align 16<br class="">+  %x = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 %i, i64 0<br class="">+  %y = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_modulo_analysis_in_loop<br class="">+; CHECK:  NoAlias: i32** %x, i32** %y<br class="">+<br class="">+define void @test_modulo_analysis_in_loop() {<br class="">+  %h = alloca [1 x [2 x i32*]], align 16<br class="">+  br label %for.loop<br class="">+<br class="">+for.loop:<br class="">+  %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]<br class="">+  %i.promoted = sext i32 %i to i64<br class="">+  %x = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 %i.promoted, i64 0<br class="">+  %y = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1<br class="">+  %i.plus1 = add nsw i32 %i, 1<br class="">+  %cmp = icmp slt i32 %i.plus1, 2<br class="">+  br i1 %cmp, label %for.loop, label %for.loop.exit<br class="">+<br class="">+for.loop.exit:<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_modulo_analysis_with_global<br class="">+; CHECK:  PartialAlias: i32** %x, i32** %y<br class="">+<br class="">+define void @test_modulo_analysis_with_global() {<br class="">+  %h = alloca [1 x [2 x i32*]], align 16<br class="">+  %b = load i32* @b, align 4<br class="">+  %b.promoted = sext i32 %b to i64<br class="">+  br label %for.loop<br class="">+<br class="">+for.loop:<br class="">+  %i = phi i32 [ 0, %0 ], [ %i.plus1, %for.loop ]<br class="">+  %i.promoted = sext i32 %i to i64<br class="">+  %x = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 %i.promoted, i64 %b.promoted<br class="">+  %y = getelementptr inbounds [1 x [2 x i32*]]* %h, i64 0, i64 0, i64 1<br class="">+  %i.plus1 = add nsw i32 %i, 1<br class="">+  %cmp = icmp slt i32 %i.plus1, 2<br class="">+  br i1 %cmp, label %for.loop, label %for.loop.exit<br class="">+<br class="">+for.loop.exit:<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_const_eval<br class="">+; CHECK: NoAlias: i8* %a, i8* %b<br class="">+define void @test_const_eval(i8* %ptr, i64 %offset) {<br class="">+  %a = getelementptr inbounds i8* %ptr, i64 %offset<br class="">+  %a.dup = getelementptr inbounds i8* %ptr, i64 %offset<br class="">+  %three = zext i32 3 to i64<br class="">+  %b = getelementptr inbounds i8* %a.dup, i64 %three<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; CHECK-LABEL: test_const_eval_scaled<br class="">+; CHECK: MustAlias: i8* %a, i8* %b<br class="">+define void @test_const_eval_scaled(i8* %ptr) {<br class="">+  %three = zext i32 3 to i64<br class="">+  %six = mul i64 %three, 2<br class="">+  %a = getelementptr inbounds i8* %ptr, i64 %six<br class="">+  %b = getelementptr inbounds i8* %ptr, i64 6<br class="">+  ret void<br class="">+}<br class="">+<br class="">+; Function Attrs: nounwind<br class="">+declare noalias i8* @malloc(i64)<br class=""><br class=""><br class="">_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a><br class=""><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br class=""></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></body></html>