[llvm] 99b3c76 - [Analysis] Optimise mul(const, (udiv %n, const)) during SCEV expansion (#212769)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 00:52:07 PDT 2026


Author: David Sherwood
Date: 2026-07-31T08:52:02+01:00
New Revision: 99b3c767c34a04af0a2bbb1fd41bf1b2cb62b331

URL: https://github.com/llvm/llvm-project/commit/99b3c767c34a04af0a2bbb1fd41bf1b2cb62b331
DIFF: https://github.com/llvm/llvm-project/commit/99b3c767c34a04af0a2bbb1fd41bf1b2cb62b331.diff

LOG: [Analysis] Optimise mul(const, (udiv %n, const)) during SCEV expansion (#212769)

We sometimes see SCEV expansions like this:

  %lshr = lshr i64 %n, 2
  %shl = shl i64 %lshr, 2

which originate from SCEV mul and udiv expressions:

  mul(4, udiv(%n, 4))

that both share the same multiplicand, divisor. The instcombine pass
normally canonicalises this into

  %and = and %n, -4

which is the final IR typically seen by the backend. In the case of SCEV
expansion during a pass like the loop vectoriser, instcombine does clean
this up. However, before this is cleaned up it will lead to
over-estimation of costs of SCEV checks, since the shifts are costed
separately and added up. It doesn't seem like there is an easy way to
look at the use count of a SCEV node in the SCEVExpander code. However,
I think for simple cases like this it's always beneficial to fold them
even if there are multiple uses of the SCEV udiv because we're dropping
both shifts.

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
    llvm/test/CodeGen/AMDGPU/memset-param-combinations.ll
    llvm/test/CodeGen/RISCV/branch-on-zero.ll
    llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
    llvm/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll
    llvm/test/Transforms/LoopIdiom/basic.ll
    llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
    llvm/test/Transforms/LoopVectorize/AArch64/reduction-cost.ll
    llvm/test/Transforms/LoopVectorize/interleaved-accesses-metadata.ll
    llvm/test/Transforms/LoopVectorize/opaque-ptr.ll
    llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index 22dc1bc8e6749..aa26b160dded7 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -599,6 +599,22 @@ Value *SCEVExpander::visitAddExpr(SCEVUseT<const SCEVAddExpr *> S) {
 Value *SCEVExpander::visitMulExpr(SCEVUseT<const SCEVMulExpr *> S) {
   Type *Ty = S->getType();
 
+  const SCEVConstant *C1, *C2;
+  const SCEV *Val;
+  // mul(PowerOf2C, (udiv X, PowerOf2C)) == (X >> C) << C
+  //  -> X & (-1 << C)
+  if (match(S, m_scev_Mul(m_SCEVConstant(C1),
+                          m_scev_UDiv(m_SCEV(Val), m_SCEVConstant(C2)))) &&
+      C1 == C2 && C1->getAPInt().isPowerOf2()) {
+    Value *LHS = expand(Val);
+    unsigned ShAmtC = C1->getAPInt().logBase2();
+    unsigned BitWidth = Ty->getScalarSizeInBits();
+    APInt Mask(APInt::getBitsSetFrom(BitWidth, ShAmtC));
+    Value *Res = InsertBinop(Instruction::And, LHS, ConstantInt::get(Ty, Mask),
+                             SCEV::FlagAnyWrap, /*IsSafeToHoist*/ true);
+    return Res;
+  }
+
   // Collect all the mul operands in a loop, along with their associated loops.
   // Iterate in reverse so that constants are emitted last, all else equal.
   SmallVector<std::pair<const Loop *, const SCEV *>, 8> OpsAndLoops;

diff  --git a/llvm/test/CodeGen/AMDGPU/memset-param-combinations.ll b/llvm/test/CodeGen/AMDGPU/memset-param-combinations.ll
index 14f56571ca056..46f654385cbc6 100644
--- a/llvm/test/CodeGen/AMDGPU/memset-param-combinations.ll
+++ b/llvm/test/CodeGen/AMDGPU/memset-param-combinations.ll
@@ -62,26 +62,24 @@ define void @memset_p0_varsize_align_4_varsetval(ptr addrspace(0) align 4 %dst,
 ; GFX942-GISEL-LABEL: memset_p0_varsize_align_4_varsetval:
 ; GFX942-GISEL:       ; %bb.0: ; %entry
 ; GFX942-GISEL-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v10, v3
-; GFX942-GISEL-NEXT:    v_mov_b64_e32 v[8:9], 15
-; GFX942-GISEL-NEXT:    v_and_b32_e32 v8, 15, v10
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v11, v4
-; GFX942-GISEL-NEXT:    v_sub_co_u32_e32 v12, vcc, v10, v8
+; GFX942-GISEL-NEXT:    v_mov_b64_e32 v[10:11], 15
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v10, 15, v3
+; GFX942-GISEL-NEXT:    v_sub_co_u32_e32 v12, vcc, v3, v10
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[0:1], 0
 ; GFX942-GISEL-NEXT:    s_nop 0
-; GFX942-GISEL-NEXT:    v_subbrev_co_u32_e32 v13, vcc, 0, v11, vcc
+; GFX942-GISEL-NEXT:    v_subbrev_co_u32_e32 v13, vcc, 0, v4, vcc
 ; GFX942-GISEL-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[12:13]
 ; GFX942-GISEL-NEXT:    s_and_saveexec_b64 s[2:3], vcc
 ; GFX942-GISEL-NEXT:    s_cbranch_execz .LBB0_3
 ; GFX942-GISEL-NEXT:  ; %bb.1: ; %dynamic-memset-expansion-main-body.preheader
-; GFX942-GISEL-NEXT:    v_and_b32_e32 v3, 0xff, v2
-; GFX942-GISEL-NEXT:    v_lshl_or_b32 v4, v3, 8, v3
-; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v5, 16, v3
-; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v3, 24, v3
-; GFX942-GISEL-NEXT:    v_or3_b32 v4, v4, v5, v3
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v5, v4
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v6, v4
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v7, v4
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v5, 0xff, v2
+; GFX942-GISEL-NEXT:    v_lshl_or_b32 v6, v5, 8, v5
+; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v7, 16, v5
+; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v5, 24, v5
+; GFX942-GISEL-NEXT:    v_or3_b32 v6, v6, v7, v5
+; GFX942-GISEL-NEXT:    v_mov_b32_e32 v7, v6
+; GFX942-GISEL-NEXT:    v_mov_b32_e32 v8, v6
+; GFX942-GISEL-NEXT:    v_mov_b32_e32 v9, v6
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[4:5], 0
 ; GFX942-GISEL-NEXT:  .LBB0_2: ; %dynamic-memset-expansion-main-body
 ; GFX942-GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
@@ -93,19 +91,21 @@ define void @memset_p0_varsize_align_4_varsetval(ptr addrspace(0) align 4 %dst,
 ; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v15, vcc, v1, v15, vcc
 ; GFX942-GISEL-NEXT:    v_cmp_ge_u64_e32 vcc, s[0:1], v[12:13]
 ; GFX942-GISEL-NEXT:    s_or_b64 s[4:5], vcc, s[4:5]
-; GFX942-GISEL-NEXT:    flat_store_dwordx4 v[14:15], v[4:7]
+; GFX942-GISEL-NEXT:    flat_store_dwordx4 v[14:15], v[6:9]
 ; GFX942-GISEL-NEXT:    s_andn2_b64 exec, exec, s[4:5]
 ; GFX942-GISEL-NEXT:    s_cbranch_execnz .LBB0_2
 ; GFX942-GISEL-NEXT:  .LBB0_3: ; %Flow4
 ; GFX942-GISEL-NEXT:    s_or_b64 exec, exec, s[2:3]
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[0:1], 0
-; GFX942-GISEL-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[8:9]
+; GFX942-GISEL-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[10:11]
 ; GFX942-GISEL-NEXT:    s_and_saveexec_b64 s[2:3], vcc
 ; GFX942-GISEL-NEXT:    s_cbranch_execz .LBB0_6
 ; GFX942-GISEL-NEXT:  ; %bb.4: ; %dynamic-memset-expansion-residual-body.preheader
-; GFX942-GISEL-NEXT:    v_lshrrev_b64 v[4:5], 4, v[10:11]
-; GFX942-GISEL-NEXT:    v_lshl_add_u64 v[0:1], v[4:5], 4, v[0:1]
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v3, -16, v3
+; GFX942-GISEL-NEXT:    v_add_co_u32_e32 v0, vcc, v0, v3
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[4:5], 0
+; GFX942-GISEL-NEXT:    s_nop 0
+; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v1, vcc, v1, v4, vcc
 ; GFX942-GISEL-NEXT:  .LBB0_5: ; %dynamic-memset-expansion-residual-body
 ; GFX942-GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
 ; GFX942-GISEL-NEXT:    v_mov_b64_e32 v[4:5], s[0:1]
@@ -114,7 +114,7 @@ define void @memset_p0_varsize_align_4_varsetval(ptr addrspace(0) align 4 %dst,
 ; GFX942-GISEL-NEXT:    s_addc_u32 s1, s1, 0
 ; GFX942-GISEL-NEXT:    s_nop 0
 ; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v5, vcc, v1, v5, vcc
-; GFX942-GISEL-NEXT:    v_cmp_ge_u64_e32 vcc, s[0:1], v[8:9]
+; GFX942-GISEL-NEXT:    v_cmp_ge_u64_e32 vcc, s[0:1], v[10:11]
 ; GFX942-GISEL-NEXT:    s_or_b64 s[4:5], vcc, s[4:5]
 ; GFX942-GISEL-NEXT:    flat_store_byte v[4:5], v2
 ; GFX942-GISEL-NEXT:    s_andn2_b64 exec, exec, s[4:5]
@@ -187,26 +187,24 @@ define void @memset_p1_varsize_align_4_varsetval(ptr addrspace(1) align 4 %dst,
 ; GFX942-GISEL-LABEL: memset_p1_varsize_align_4_varsetval:
 ; GFX942-GISEL:       ; %bb.0: ; %entry
 ; GFX942-GISEL-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v10, v3
-; GFX942-GISEL-NEXT:    v_mov_b64_e32 v[8:9], 15
-; GFX942-GISEL-NEXT:    v_and_b32_e32 v8, 15, v10
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v11, v4
-; GFX942-GISEL-NEXT:    v_sub_co_u32_e32 v12, vcc, v10, v8
+; GFX942-GISEL-NEXT:    v_mov_b64_e32 v[10:11], 15
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v10, 15, v3
+; GFX942-GISEL-NEXT:    v_sub_co_u32_e32 v12, vcc, v3, v10
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[0:1], 0
 ; GFX942-GISEL-NEXT:    s_nop 0
-; GFX942-GISEL-NEXT:    v_subbrev_co_u32_e32 v13, vcc, 0, v11, vcc
+; GFX942-GISEL-NEXT:    v_subbrev_co_u32_e32 v13, vcc, 0, v4, vcc
 ; GFX942-GISEL-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[12:13]
 ; GFX942-GISEL-NEXT:    s_and_saveexec_b64 s[2:3], vcc
 ; GFX942-GISEL-NEXT:    s_cbranch_execz .LBB1_3
 ; GFX942-GISEL-NEXT:  ; %bb.1: ; %dynamic-memset-expansion-main-body.preheader
-; GFX942-GISEL-NEXT:    v_and_b32_e32 v3, 0xff, v2
-; GFX942-GISEL-NEXT:    v_lshl_or_b32 v4, v3, 8, v3
-; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v5, 16, v3
-; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v3, 24, v3
-; GFX942-GISEL-NEXT:    v_or3_b32 v4, v4, v5, v3
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v5, v4
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v6, v4
-; GFX942-GISEL-NEXT:    v_mov_b32_e32 v7, v4
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v5, 0xff, v2
+; GFX942-GISEL-NEXT:    v_lshl_or_b32 v6, v5, 8, v5
+; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v7, 16, v5
+; GFX942-GISEL-NEXT:    v_lshlrev_b32_e32 v5, 24, v5
+; GFX942-GISEL-NEXT:    v_or3_b32 v6, v6, v7, v5
+; GFX942-GISEL-NEXT:    v_mov_b32_e32 v7, v6
+; GFX942-GISEL-NEXT:    v_mov_b32_e32 v8, v6
+; GFX942-GISEL-NEXT:    v_mov_b32_e32 v9, v6
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[4:5], 0
 ; GFX942-GISEL-NEXT:  .LBB1_2: ; %dynamic-memset-expansion-main-body
 ; GFX942-GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
@@ -218,19 +216,21 @@ define void @memset_p1_varsize_align_4_varsetval(ptr addrspace(1) align 4 %dst,
 ; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v15, vcc, v1, v15, vcc
 ; GFX942-GISEL-NEXT:    v_cmp_ge_u64_e32 vcc, s[0:1], v[12:13]
 ; GFX942-GISEL-NEXT:    s_or_b64 s[4:5], vcc, s[4:5]
-; GFX942-GISEL-NEXT:    global_store_dwordx4 v[14:15], v[4:7], off
+; GFX942-GISEL-NEXT:    global_store_dwordx4 v[14:15], v[6:9], off
 ; GFX942-GISEL-NEXT:    s_andn2_b64 exec, exec, s[4:5]
 ; GFX942-GISEL-NEXT:    s_cbranch_execnz .LBB1_2
 ; GFX942-GISEL-NEXT:  .LBB1_3: ; %Flow4
 ; GFX942-GISEL-NEXT:    s_or_b64 exec, exec, s[2:3]
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[0:1], 0
-; GFX942-GISEL-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[8:9]
+; GFX942-GISEL-NEXT:    v_cmp_ne_u64_e32 vcc, 0, v[10:11]
 ; GFX942-GISEL-NEXT:    s_and_saveexec_b64 s[2:3], vcc
 ; GFX942-GISEL-NEXT:    s_cbranch_execz .LBB1_6
 ; GFX942-GISEL-NEXT:  ; %bb.4: ; %dynamic-memset-expansion-residual-body.preheader
-; GFX942-GISEL-NEXT:    v_lshrrev_b64 v[4:5], 4, v[10:11]
-; GFX942-GISEL-NEXT:    v_lshl_add_u64 v[0:1], v[4:5], 4, v[0:1]
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v3, -16, v3
+; GFX942-GISEL-NEXT:    v_add_co_u32_e32 v0, vcc, v0, v3
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[4:5], 0
+; GFX942-GISEL-NEXT:    s_nop 0
+; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v1, vcc, v1, v4, vcc
 ; GFX942-GISEL-NEXT:  .LBB1_5: ; %dynamic-memset-expansion-residual-body
 ; GFX942-GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
 ; GFX942-GISEL-NEXT:    v_mov_b64_e32 v[4:5], s[0:1]
@@ -239,7 +239,7 @@ define void @memset_p1_varsize_align_4_varsetval(ptr addrspace(1) align 4 %dst,
 ; GFX942-GISEL-NEXT:    s_addc_u32 s1, s1, 0
 ; GFX942-GISEL-NEXT:    s_nop 0
 ; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v5, vcc, v1, v5, vcc
-; GFX942-GISEL-NEXT:    v_cmp_ge_u64_e32 vcc, s[0:1], v[8:9]
+; GFX942-GISEL-NEXT:    v_cmp_ge_u64_e32 vcc, s[0:1], v[10:11]
 ; GFX942-GISEL-NEXT:    s_or_b64 s[4:5], vcc, s[4:5]
 ; GFX942-GISEL-NEXT:    global_store_byte v[4:5], v2, off
 ; GFX942-GISEL-NEXT:    s_andn2_b64 exec, exec, s[4:5]
@@ -1740,9 +1740,11 @@ define void @memset_p1_varsz_align_4_set40(ptr addrspace(1) align 4 %dst, i64 %s
 ; GFX942-GISEL-NEXT:    s_and_saveexec_b64 s[2:3], vcc
 ; GFX942-GISEL-NEXT:    s_cbranch_execz .LBB12_6
 ; GFX942-GISEL-NEXT:  ; %bb.4: ; %dynamic-memset-expansion-residual-body.preheader
-; GFX942-GISEL-NEXT:    v_lshrrev_b64 v[2:3], 4, v[2:3]
-; GFX942-GISEL-NEXT:    v_lshl_add_u64 v[0:1], v[2:3], 4, v[0:1]
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v2, -16, v2
+; GFX942-GISEL-NEXT:    v_add_co_u32_e32 v0, vcc, v0, v2
 ; GFX942-GISEL-NEXT:    v_mov_b32_e32 v2, 40
+; GFX942-GISEL-NEXT:    s_nop 0
+; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v1, vcc, v1, v3, vcc
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[4:5], 0
 ; GFX942-GISEL-NEXT:  .LBB12_5: ; %dynamic-memset-expansion-residual-body
 ; GFX942-GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
@@ -1860,9 +1862,11 @@ define void @memset_p1_varsz_align_4_set0(ptr addrspace(1) align 4 %dst, i64 %si
 ; GFX942-GISEL-NEXT:    s_and_saveexec_b64 s[2:3], vcc
 ; GFX942-GISEL-NEXT:    s_cbranch_execz .LBB13_6
 ; GFX942-GISEL-NEXT:  ; %bb.4: ; %dynamic-memset-expansion-residual-body.preheader
-; GFX942-GISEL-NEXT:    v_lshrrev_b64 v[2:3], 4, v[2:3]
-; GFX942-GISEL-NEXT:    v_lshl_add_u64 v[0:1], v[2:3], 4, v[0:1]
+; GFX942-GISEL-NEXT:    v_and_b32_e32 v2, -16, v2
+; GFX942-GISEL-NEXT:    v_add_co_u32_e32 v0, vcc, v0, v2
 ; GFX942-GISEL-NEXT:    v_mov_b32_e32 v2, 0
+; GFX942-GISEL-NEXT:    s_nop 0
+; GFX942-GISEL-NEXT:    v_addc_co_u32_e32 v1, vcc, v1, v3, vcc
 ; GFX942-GISEL-NEXT:    s_mov_b64 s[4:5], 0
 ; GFX942-GISEL-NEXT:  .LBB13_5: ; %dynamic-memset-expansion-residual-body
 ; GFX942-GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1

diff  --git a/llvm/test/CodeGen/RISCV/branch-on-zero.ll b/llvm/test/CodeGen/RISCV/branch-on-zero.ll
index b77809308ad9c..fa1823cadd1f8 100644
--- a/llvm/test/CodeGen/RISCV/branch-on-zero.ll
+++ b/llvm/test/CodeGen/RISCV/branch-on-zero.ll
@@ -119,10 +119,10 @@ for.end:                                          ; preds = %for.body, %entry
 define i32 @test_lshr2(ptr nocapture %x, ptr nocapture readonly %y, i32 %n) {
 ; RV32-LABEL: test_lshr2:
 ; RV32:       # %bb.0: # %entry
-; RV32-NEXT:    srli a2, a2, 2
-; RV32-NEXT:    beqz a2, .LBB3_3
+; RV32-NEXT:    li a3, 4
+; RV32-NEXT:    bltu a2, a3, .LBB3_3
 ; RV32-NEXT:  # %bb.1: # %while.body.preheader
-; RV32-NEXT:    slli a2, a2, 2
+; RV32-NEXT:    andi a2, a2, -4
 ; RV32-NEXT:    add a2, a1, a2
 ; RV32-NEXT:  .LBB3_2: # %while.body
 ; RV32-NEXT:    # =>This Inner Loop Header: Depth=1

diff  --git a/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll b/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
index 7080707bc1de9..712b6ae399f2e 100644
--- a/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
+++ b/llvm/test/Transforms/IndVarSimplify/ARM/code-size.ll
@@ -12,8 +12,7 @@ define i32 @remove_loop(i32 %size) #0 {
 ; CHECK-V8M-NEXT:    [[TMP0:%.*]] = add i32 [[SIZE:%.*]], 31
 ; CHECK-V8M-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SIZE]], i32 31)
 ; CHECK-V8M-NEXT:    [[TMP1:%.*]] = sub i32 [[TMP0]], [[UMIN]]
-; CHECK-V8M-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP1]], 5
-; CHECK-V8M-NEXT:    [[TMP3:%.*]] = shl nuw i32 [[TMP2]], 5
+; CHECK-V8M-NEXT:    [[TMP3:%.*]] = and i32 [[TMP1]], -32
 ; CHECK-V8M-NEXT:    [[TMP4:%.*]] = sub i32 [[SIZE]], [[TMP3]]
 ; CHECK-V8M-NEXT:    ret i32 [[TMP4]]
 ;
@@ -26,8 +25,7 @@ define i32 @remove_loop(i32 %size) #0 {
 ; CHECK-V8A-NEXT:    [[TMP0:%.*]] = add i32 [[SIZE:%.*]], 31
 ; CHECK-V8A-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SIZE]], i32 31)
 ; CHECK-V8A-NEXT:    [[TMP1:%.*]] = sub i32 [[TMP0]], [[UMIN]]
-; CHECK-V8A-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP1]], 5
-; CHECK-V8A-NEXT:    [[TMP3:%.*]] = shl nuw i32 [[TMP2]], 5
+; CHECK-V8A-NEXT:    [[TMP3:%.*]] = and i32 [[TMP1]], -32
 ; CHECK-V8A-NEXT:    [[TMP4:%.*]] = sub i32 [[SIZE]], [[TMP3]]
 ; CHECK-V8A-NEXT:    ret i32 [[TMP4]]
 ;

diff  --git a/llvm/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll b/llvm/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll
index b3162de0f2245..aa35b1f63a57a 100644
--- a/llvm/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll
+++ b/llvm/test/Transforms/IndVarSimplify/replace-loop-exit-folds.ll
@@ -4,21 +4,19 @@
 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
 
 define i32 @remove_loop(i32 %size) {
-; CHECK-LABEL: define i32 @remove_loop(
-; CHECK-SAME: i32 [[SIZE:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*]]:
-; CHECK-NEXT:    br label %[[WHILE_COND:.*]]
-; CHECK:       [[WHILE_COND]]:
-; CHECK-NEXT:    [[SIZE_ADDR_0:%.*]] = phi i32 [ [[SIZE]], %[[ENTRY]] ], [ [[SUB:%.*]], %[[WHILE_COND]] ]
+; CHECK-LABEL: @remove_loop(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+; CHECK:       while.cond:
+; CHECK-NEXT:    [[SIZE_ADDR_0:%.*]] = phi i32 [ [[SIZE:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[WHILE_COND]] ]
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[SIZE_ADDR_0]], 31
 ; CHECK-NEXT:    [[SUB]] = add i32 [[SIZE_ADDR_0]], -32
-; CHECK-NEXT:    br i1 [[CMP]], label %[[WHILE_COND]], label %[[WHILE_END:.*]]
-; CHECK:       [[WHILE_END]]:
+; CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_COND]], label [[WHILE_END:%.*]]
+; CHECK:       while.end:
 ; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[SIZE]], 31
 ; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SIZE]], i32 31)
 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[TMP0]], [[UMIN]]
-; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP1]], 5
-; CHECK-NEXT:    [[TMP3:%.*]] = shl nuw i32 [[TMP2]], 5
+; CHECK-NEXT:    [[TMP3:%.*]] = and i32 [[TMP1]], -32
 ; CHECK-NEXT:    [[TMP4:%.*]] = sub i32 [[SIZE]], [[TMP3]]
 ; CHECK-NEXT:    ret i32 [[TMP4]]
 ;

diff  --git a/llvm/test/Transforms/LoopIdiom/basic.ll b/llvm/test/Transforms/LoopIdiom/basic.ll
index f54e5acefbccc..98a1f2bb40e23 100644
--- a/llvm/test/Transforms/LoopIdiom/basic.ll
+++ b/llvm/test/Transforms/LoopIdiom/basic.ll
@@ -1200,8 +1200,7 @@ define void @loop_with_memcpy_stride16(ptr %Src, i64 %Size) {
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 16
 ; CHECK-NEXT:    [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[SIZE:%.*]], i64 16)
 ; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
-; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 4
-; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw nsw i64 [[TMP1]], 4
+; CHECK-NEXT:    [[TMP2:%.*]] = and i64 [[TMP0]], -16
 ; CHECK-NEXT:    [[TMP3:%.*]] = add nuw i64 [[TMP2]], 16
 ; CHECK-NEXT:    call void @llvm.memmove.p0.p0.i64(ptr align 1 [[SRC]], ptr align 1 [[SCEVGEP]], i64 [[TMP3]], i1 false)
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]

diff  --git a/llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll b/llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
index b842e1677be35..89da5eafaac6d 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/AArch64/expand-ptrtoaddr-reuse-ptrtoint.ll
@@ -14,8 +14,7 @@ define i64 @expand_reuses_existing_ptrtoint(ptr %begin, ptr %end, ptr %cap) {
 ; CHECK:       [[COUNT_PH]]:
 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[END1]], -8
 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 [[TMP0]], [[BEGIN2]]
-; CHECK-NEXT:    [[TMP2:%.*]] = lshr i64 [[TMP1]], 3
-; CHECK-NEXT:    [[TMP3:%.*]] = shl nuw i64 [[TMP2]], 3
+; CHECK-NEXT:    [[TMP3:%.*]] = and i64 [[TMP1]], -8
 ; CHECK-NEXT:    [[TMP4:%.*]] = add i64 [[TMP3]], 8
 ; CHECK-NEXT:    br label %[[COUNT:.*]]
 ; CHECK:       [[COUNT]]:

diff  --git a/llvm/test/Transforms/LoopVectorize/AArch64/reduction-cost.ll b/llvm/test/Transforms/LoopVectorize/AArch64/reduction-cost.ll
index af6166be4ab42..d75ba89d44539 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/reduction-cost.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/reduction-cost.ll
@@ -108,8 +108,7 @@ define i32 @or_reduction_with_freeze(ptr %dst, ptr %src) {
 ; CHECK-NEXT:    br i1 [[IDENT_CHECK]], label %[[SCALAR_PH]], label %[[VECTOR_MEMCHECK:.*]]
 ; CHECK:       [[VECTOR_MEMCHECK]]:
 ; CHECK-NEXT:    [[TMP7:%.*]] = sub i64 [[DST1]], [[SRC7]]
-; CHECK-NEXT:    [[TMP8:%.*]] = lshr i64 [[TMP7]], 3
-; CHECK-NEXT:    [[TMP9:%.*]] = shl nuw i64 [[TMP8]], 3
+; CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP7]], -8
 ; CHECK-NEXT:    [[TMP10:%.*]] = add i64 [[TMP9]], 8
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP10]]
 ; CHECK-NEXT:    [[SCEVGEP5:%.*]] = getelementptr i8, ptr [[DST]], i64 8

diff  --git a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-metadata.ll b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-metadata.ll
index a20359e48d98d..db03eb1464735 100644
--- a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-metadata.ll
+++ b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-metadata.ll
@@ -87,8 +87,7 @@ define void @ir_tbaa_
diff erent(ptr %base, ptr %end, ptr %src) {
 ; CHECK:       [[VECTOR_MEMCHECK]]:
 ; CHECK-NEXT:    [[TMP17:%.*]] = add i64 [[END2]], -8
 ; CHECK-NEXT:    [[TMP12:%.*]] = sub i64 [[TMP17]], [[BASE2]]
-; CHECK-NEXT:    [[TMP13:%.*]] = lshr i64 [[TMP12]], 3
-; CHECK-NEXT:    [[TMP14:%.*]] = shl nuw i64 [[TMP13]], 3
+; CHECK-NEXT:    [[TMP14:%.*]] = and i64 [[TMP12]], -8
 ; CHECK-NEXT:    [[TMP15:%.*]] = add i64 [[TMP14]], 8
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[TMP15]]
 ; CHECK-NEXT:    [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[SRC]], i64 4

diff  --git a/llvm/test/Transforms/LoopVectorize/opaque-ptr.ll b/llvm/test/Transforms/LoopVectorize/opaque-ptr.ll
index 7c5a0481c9e57..e5f9b0c84195a 100644
--- a/llvm/test/Transforms/LoopVectorize/opaque-ptr.ll
+++ b/llvm/test/Transforms/LoopVectorize/opaque-ptr.ll
@@ -22,8 +22,7 @@ define void @test_ptr_iv_no_inbounds(ptr %p1.start, ptr %p2.start, ptr %p1.end)
 ; CHECK:       vector.memcheck:
 ; CHECK-NEXT:    [[TMP15:%.*]] = add i64 [[TMP8]], -4
 ; CHECK-NEXT:    [[TMP9:%.*]] = sub i64 [[TMP15]], [[P1_END1]]
-; CHECK-NEXT:    [[TMP10:%.*]] = lshr i64 [[TMP9]], 2
-; CHECK-NEXT:    [[TMP11:%.*]] = shl nuw i64 [[TMP10]], 2
+; CHECK-NEXT:    [[TMP11:%.*]] = and i64 [[TMP9]], -4
 ; CHECK-NEXT:    [[TMP12:%.*]] = add i64 [[TMP11]], 4
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[P1_END]], i64 [[TMP12]]
 ; CHECK-NEXT:    [[SCEVGEP5:%.*]] = getelementptr i8, ptr [[P2_START:%.*]], i64 [[TMP12]]
@@ -104,8 +103,7 @@ define void @test_ptr_iv_with_inbounds(ptr %p1.start, ptr %p2.start, ptr %p1.end
 ; CHECK:       vector.memcheck:
 ; CHECK-NEXT:    [[TMP11:%.*]] = add i64 [[TMP4]], -4
 ; CHECK-NEXT:    [[TMP5:%.*]] = sub i64 [[TMP11]], [[P1_END1]]
-; CHECK-NEXT:    [[TMP6:%.*]] = lshr i64 [[TMP5]], 2
-; CHECK-NEXT:    [[TMP7:%.*]] = shl nuw i64 [[TMP6]], 2
+; CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP5]], -4
 ; CHECK-NEXT:    [[TMP8:%.*]] = add i64 [[TMP7]], 4
 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[P1_END]], i64 [[TMP8]]
 ; CHECK-NEXT:    [[SCEVGEP3:%.*]] = getelementptr i8, ptr [[P2_START:%.*]], i64 [[TMP8]]

diff  --git a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
index 5dcc833d8893f..f2c0ad7d26a3c 100644
--- a/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
+++ b/llvm/unittests/Transforms/Utils/ScalarEvolutionExpanderTest.cpp
@@ -700,8 +700,7 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpanderShlNSW) {
 
     SCEVExpander Exp(SE, "expander");
     auto *I = cast<Instruction>(Exp.expandCodeFor(AndSCEV, nullptr, And));
-    EXPECT_EQ(I->getOpcode(), Instruction::Shl);
-    EXPECT_FALSE(I->hasNoSignedWrap());
+    EXPECT_EQ(I->getOpcode(), Instruction::And);
   };
 
   checkOneCase("define void @f(ptr %arrayidx) { "


        


More information about the llvm-commits mailing list