[llvm] 0952cf5 - [InstCombine] decomposeSimpleLinearExpr should bail out on negative operands.

Wael Yehia via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 7 17:58:12 PDT 2022


Author: Wael Yehia
Date: 2022-06-08T00:57:25Z
New Revision: 0952cf5bbbc4bc5470443b53e07c88fb0013b42a

URL: https://github.com/llvm/llvm-project/commit/0952cf5bbbc4bc5470443b53e07c88fb0013b42a
DIFF: https://github.com/llvm/llvm-project/commit/0952cf5bbbc4bc5470443b53e07c88fb0013b42a.diff

LOG: [InstCombine] decomposeSimpleLinearExpr should bail out on negative operands.

InstCombine tries to rewrite

  %prod = mul nsw i64 %X,   Scale
  %acc = add nsw i64 %prod,   Offset
  %0 = alloca i8, i64 %acc, align 4
  %1 = bitcast i8* %0 to i32*
  Use ( %1 )

into

  %prod = mul nsw i64 %X,   Scale/4
  %acc = add nsw i64 %prod,   Offset/4
  %0 = alloca i32, i64 %acc, align 4
  Use (%0)

But it assumes Scale is unsigned, and performs an unsigned division.
So we should bail out if Scale cannot be interpreted as an unsigned safely.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D126546

Added: 
    llvm/test/Transforms/InstCombine/neg-alloca.ll

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
    llvm/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index c3fb0b542e5c..bdd5e00983bd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -36,8 +36,10 @@ static Value *decomposeSimpleLinearExpr(Value *Val, unsigned &Scale,
 
   if (BinaryOperator *I = dyn_cast<BinaryOperator>(Val)) {
     // Cannot look past anything that might overflow.
+    // We specifically require nuw because we store the Scale in an unsigned
+    // and perform an unsigned divide on it.
     OverflowingBinaryOperator *OBI = dyn_cast<OverflowingBinaryOperator>(Val);
-    if (OBI && !OBI->hasNoUnsignedWrap() && !OBI->hasNoSignedWrap()) {
+    if (OBI && !OBI->hasNoUnsignedWrap()) {
       Scale = 1;
       Offset = 0;
       return Val;

diff  --git a/llvm/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll b/llvm/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll
index dd0d83705abe..addb862949c4 100644
--- a/llvm/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll
+++ b/llvm/test/Transforms/InstCombine/2011-06-13-nsw-alloca.ll
@@ -15,9 +15,9 @@ define void @fu1(i32 %parm) nounwind ssp {
 
 ; <label>:4                                       ; preds = %0
   %5 = load i32, i32* %1, align 4
-  %6 = shl nsw i32 %5, 3
-; With "nsw", the alloca and its bitcast can be fused:
-  %7 = add nsw i32 %6, 2048
+  %6 = shl nuw i32 %5, 3
+; With "nuw", the alloca and its bitcast can be fused:
+  %7 = add nuw i32 %6, 2048
 ;  CHECK: alloca double
   %8 = alloca i8, i32 %7
   %9 = bitcast i8* %8 to double*
@@ -45,8 +45,8 @@ define void @fu2(i32 %parm) nounwind ssp {
 
 ; <label>:4                                       ; preds = %0
   %5 = load i32, i32* %1, align 4
-  %6 = mul nsw i32 %5, 8
-; Without "nsw", the alloca and its bitcast cannot be fused:
+  %6 = mul nuw i32 %5, 8
+; Without "nuw", the alloca and its bitcast cannot be fused:
   %7 = add  i32 %6, 2048
 ; CHECK: alloca i8
   %8 = alloca i8, i32 %7

diff  --git a/llvm/test/Transforms/InstCombine/neg-alloca.ll b/llvm/test/Transforms/InstCombine/neg-alloca.ll
new file mode 100644
index 000000000000..13e5afc5dade
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/neg-alloca.ll
@@ -0,0 +1,21 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+declare void @use(i32 *)
+
+define void @foo(i64 %X) {
+; Currently we cannot handle expressions of the form Offset - X * Scale.
+; CHECK-LABEL: @foo(
+; CHECK-NEXT:    [[TMP1:%.*]] = mul nsw i64 [[X:%.*]], -4
+; CHECK-NEXT:    [[TMP2:%.*]] = add nsw i64 [[TMP1]], 24
+; CHECK-NEXT:    [[TMP3:%.*]] = alloca i8, i64 [[TMP2]], align 4
+; CHECK-NEXT:    [[TMP4:%.*]] = bitcast i8* [[TMP3]] to i32*
+; CHECK-NEXT:    call void @use(i32* nonnull [[TMP4]])
+; CHECK-NEXT:    ret void
+;
+  %1 = mul nsw i64 %X, -4
+  %2 = add nsw i64 %1, 24
+  %3 = alloca i8, i64 %2, align 4
+  %4 = bitcast i8* %3 to i32*
+  call void @use(i32 *%4)
+  ret void
+}


        


More information about the llvm-commits mailing list