diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -36,8 +36,10 @@ 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 --- 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 @@ ; <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 @@ ; <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 --- /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 +}