; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -mtriple=armv8m.main-none-none-eabi -mattr=+dsp < %s -arm-parallel-dsp -verify -S | FileCheck %s
;
; Alias check: check that the rewrite isn't triggered when there's a store
; instruction possibly aliasing any mul load operands; arguments are passed
; without 'restrict' enabled.
;
define dso_local i32 @no_restrict(i32 %arg, ptr nocapture %arg1, ptr nocapture readonly %arg2, ptr nocapture readonly %arg3) {
; CHECK-LABEL: @no_restrict(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD11:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[ADD11]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP2]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV]], [[CONV4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[CONV7]], [[CONV8]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2

; Store inserted here, aliasing with arrayidx, arrayidx1, arrayidx3
  store i16 42, ptr %arrayidx, align 2

  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

; Alias check: check that the rewrite isn't triggered when there's a store
; aliasing one of the mul load operands. Arguments are now annotated with
; 'noalias'.
;
define dso_local i32 @restrict(i32 %arg, ptr noalias %arg1, ptr noalias readonly %arg2, ptr noalias %arg3) {
; CHECK-LABEL: @restrict(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD11:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[ADD11]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP2]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV]], [[CONV4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[CONV7]], [[CONV8]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2

; Store inserted here, aliasing only with loads from 'arrayidx'.
  store i16 42, ptr %arrayidx, align 2

  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026

; Here the Mul is the LHS, and the Add the RHS.
  %add11 = add i32 %mul9, %add10

  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @store_dominates_all(i32 %arg, ptr nocapture %arg1, ptr nocapture readonly %arg2, ptr nocapture readonly %arg3) {
; CHECK-LABEL: @store_dominates_all(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP13:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[TMP13]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
; CHECK-NEXT:    [[TMP4:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[TMP5:%.*]] = lshr i32 [[TMP2]], 16
; CHECK-NEXT:    [[TMP6:%.*]] = trunc i32 [[TMP5]] to i16
; CHECK-NEXT:    [[TMP7:%.*]] = sext i16 [[TMP6]] to i32
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP8:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP9:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP12:%.*]] = trunc i32 [[TMP11]] to i16
; CHECK-NEXT:    [[TMP13]] = call i32 @llvm.arm.smlad(i32 [[TMP11]], i32 [[TMP2]], i32 [[MAC1_026]])
; CHECK-NEXT:    [[TMP14:%.*]] = sext i16 [[TMP12]] to i32
; CHECK-NEXT:    [[TMP15:%.*]] = lshr i32 [[TMP11]], 16
; CHECK-NEXT:    [[TMP16:%.*]] = trunc i32 [[TMP15]] to i16
; CHECK-NEXT:    [[TMP17:%.*]] = sext i16 [[TMP16]] to i32
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP9]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[TMP14]], [[TMP4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP18:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP18]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP8]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[TMP17]], [[TMP7]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11:%.*]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  store i16 42, ptr %arrayidx, align 2
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @loads_dominate(i32 %arg, ptr nocapture %arg1, ptr nocapture readonly %arg2, ptr nocapture readonly %arg3) {
; CHECK-LABEL: @loads_dominate(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP13:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[TMP13]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
; CHECK-NEXT:    [[TMP4:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[TMP5:%.*]] = lshr i32 [[TMP2]], 16
; CHECK-NEXT:    [[TMP6:%.*]] = trunc i32 [[TMP5]] to i16
; CHECK-NEXT:    [[TMP7:%.*]] = sext i16 [[TMP6]] to i32
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP8:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP9:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP12:%.*]] = trunc i32 [[TMP11]] to i16
; CHECK-NEXT:    [[TMP13]] = call i32 @llvm.arm.smlad(i32 [[TMP11]], i32 [[TMP2]], i32 [[MAC1_026]])
; CHECK-NEXT:    [[TMP14:%.*]] = sext i16 [[TMP12]] to i32
; CHECK-NEXT:    [[TMP15:%.*]] = lshr i32 [[TMP11]], 16
; CHECK-NEXT:    [[TMP16:%.*]] = trunc i32 [[TMP15]] to i16
; CHECK-NEXT:    [[TMP17:%.*]] = sext i16 [[TMP16]] to i32
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP9]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[TMP14]], [[TMP4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP18:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP18]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP8]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[TMP17]], [[TMP7]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11:%.*]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  store i16 42, ptr %arrayidx, align 2
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @store_alias_arg3_legal_1(i32 %arg, ptr nocapture %arg1, ptr noalias nocapture readonly %arg2, ptr nocapture readonly %arg3) {
; CHECK-LABEL: @store_alias_arg3_legal_1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP13:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[TMP13]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
; CHECK-NEXT:    [[TMP4:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[TMP5:%.*]] = lshr i32 [[TMP2]], 16
; CHECK-NEXT:    [[TMP6:%.*]] = trunc i32 [[TMP5]] to i16
; CHECK-NEXT:    [[TMP7:%.*]] = sext i16 [[TMP6]] to i32
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP8:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP9:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP12:%.*]] = trunc i32 [[TMP11]] to i16
; CHECK-NEXT:    [[TMP13]] = call i32 @llvm.arm.smlad(i32 [[TMP11]], i32 [[TMP2]], i32 [[MAC1_026]])
; CHECK-NEXT:    [[TMP14:%.*]] = sext i16 [[TMP12]] to i32
; CHECK-NEXT:    [[TMP15:%.*]] = lshr i32 [[TMP11]], 16
; CHECK-NEXT:    [[TMP16:%.*]] = trunc i32 [[TMP15]] to i16
; CHECK-NEXT:    [[TMP17:%.*]] = sext i16 [[TMP16]] to i32
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP9]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[TMP14]], [[TMP4]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP18:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP18]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP8]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[TMP17]], [[TMP7]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11:%.*]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  store i16 42, ptr %arrayidx, align 2
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @store_alias_arg3_legal_2(i32 %arg, ptr nocapture %arg1, ptr noalias nocapture readonly %arg2, ptr nocapture readonly %arg3) {
; CHECK-LABEL: @store_alias_arg3_legal_2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP13:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[TMP13]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[TMP2]] to i16
; CHECK-NEXT:    [[TMP4:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[TMP5:%.*]] = lshr i32 [[TMP2]], 16
; CHECK-NEXT:    [[TMP6:%.*]] = trunc i32 [[TMP5]] to i16
; CHECK-NEXT:    [[TMP7:%.*]] = sext i16 [[TMP6]] to i32
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP8:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP9:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP11:%.*]] = load i32, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP12:%.*]] = trunc i32 [[TMP11]] to i16
; CHECK-NEXT:    [[TMP13]] = call i32 @llvm.arm.smlad(i32 [[TMP11]], i32 [[TMP2]], i32 [[MAC1_026]])
; CHECK-NEXT:    [[TMP14:%.*]] = sext i16 [[TMP12]] to i32
; CHECK-NEXT:    [[TMP15:%.*]] = lshr i32 [[TMP11]], 16
; CHECK-NEXT:    [[TMP16:%.*]] = trunc i32 [[TMP15]] to i16
; CHECK-NEXT:    [[TMP17:%.*]] = sext i16 [[TMP16]] to i32
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP9]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[TMP14]], [[TMP4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP18:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP18]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP8]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[TMP17]], [[TMP7]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11:%.*]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  store i16 42, ptr %arrayidx, align 2
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @store_alias_arg3_illegal_1(i32 %arg, ptr nocapture %arg1, ptr noalias nocapture readonly %arg2, ptr noalias nocapture %arg3) {
; CHECK-LABEL: @store_alias_arg3_illegal_1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD11:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[ADD11]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP2]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV]], [[CONV4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[CONV7]], [[CONV8]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  store i16 42, ptr %arrayidx1, align 2
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @store_alias_arg3_illegal_2(i32 %arg, ptr nocapture %arg1, ptr noalias nocapture readonly %arg2, ptr noalias nocapture %arg3) {
; CHECK-LABEL: @store_alias_arg3_illegal_2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD11:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[ADD11]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP2]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV]], [[CONV4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[CONV7]], [[CONV8]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  store i16 42, ptr %arrayidx, align 2
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @store_alias_arg2_illegal_1(i32 %arg, ptr nocapture %arg1, ptr nocapture readonly %arg2, ptr nocapture readonly %arg3) {
; CHECK-LABEL: @store_alias_arg2_illegal_1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD11:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[ADD11]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP2]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV]], [[CONV4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[CONV7]], [[CONV8]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  store i16 42, ptr %arrayidx6, align 2
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

define dso_local i32 @store_alias_arg2_illegal_2(i32 %arg, ptr nocapture %arg1, ptr nocapture readonly %arg2, ptr nocapture readonly %arg3) {
; CHECK-LABEL: @store_alias_arg2_illegal_2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP24:%.*]] = icmp sgt i32 [[ARG:%.*]], 0
; CHECK-NEXT:    br i1 [[CMP24]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CHECK:       for.body.preheader:
; CHECK-NEXT:    [[DOTPRE:%.*]] = load i16, ptr [[ARG3:%.*]], align 2
; CHECK-NEXT:    [[DOTPRE27:%.*]] = load i16, ptr [[ARG2:%.*]], align 2
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    [[MAC1_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD11:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    ret i32 [[MAC1_0_LCSSA]]
; CHECK:       for.body:
; CHECK-NEXT:    [[MAC1_026:%.*]] = phi i32 [ [[ADD11]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[I_025:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[ADD]] = add nuw nsw i32 [[I_025]], 1
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[ARG3]], i32 [[ADD]]
; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[I_025]]
; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP2]] to i32
; CHECK-NEXT:    [[CONV4:%.*]] = sext i16 [[TMP0]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV]], [[CONV4]]
; CHECK-NEXT:    [[ARRAYIDX6:%.*]] = getelementptr inbounds i16, ptr [[ARG2]], i32 [[ADD]]
; CHECK-NEXT:    store i16 42, ptr [[ARRAYIDX3]], align 2
; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX6]], align 2
; CHECK-NEXT:    [[CONV7:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[CONV7]], [[CONV8]]
; CHECK-NEXT:    [[ADD10:%.*]] = add i32 [[MUL]], [[MAC1_026]]
; CHECK-NEXT:    [[ADD11]] = add i32 [[MUL9]], [[ADD10]]
; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[ADD]], [[ARG]]
; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP]]
;
entry:
  %cmp24 = icmp sgt i32 %arg, 0
  br i1 %cmp24, label %for.body.preheader, label %for.cond.cleanup

for.body.preheader:
  %.pre = load i16, ptr %arg3, align 2
  %.pre27 = load i16, ptr %arg2, align 2
  br label %for.body

for.cond.cleanup:
  %mac1.0.lcssa = phi i32 [ 0, %entry ], [ %add11, %for.body ]
  ret i32 %mac1.0.lcssa

for.body:
  %mac1.026 = phi i32 [ %add11, %for.body ], [ 0, %for.body.preheader ]
  %i.025 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
  %arrayidx = getelementptr inbounds i16, ptr %arg3, i32 %i.025
  %0 = load i16, ptr %arrayidx, align 2
  %add = add nuw nsw i32 %i.025, 1
  %arrayidx1 = getelementptr inbounds i16, ptr %arg3, i32 %add
  %1 = load i16, ptr %arrayidx1, align 2
  %arrayidx3 = getelementptr inbounds i16, ptr %arg2, i32 %i.025
  %2 = load i16, ptr %arrayidx3, align 2
  %conv = sext i16 %2 to i32
  %conv4 = sext i16 %0 to i32
  %mul = mul nsw i32 %conv, %conv4
  %arrayidx6 = getelementptr inbounds i16, ptr %arg2, i32 %add
  store i16 42, ptr %arrayidx3, align 2
  %3 = load i16, ptr %arrayidx6, align 2
  %conv7 = sext i16 %3 to i32
  %conv8 = sext i16 %1 to i32
  %mul9 = mul nsw i32 %conv7, %conv8
  %add10 = add i32 %mul, %mac1.026
  %add11 = add i32 %mul9, %add10
  %exitcond = icmp ne i32 %add, %arg
  br i1 %exitcond, label %for.body, label %for.cond.cleanup
}

; TODO: I think we should be able to generate one smlad here. The search fails
; when it finds the alias.
define i32 @one_pair_alias(ptr noalias nocapture readonly %b, ptr noalias nocapture %c) {
; CHECK-LABEL: @one_pair_alias(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond.cleanup:
; CHECK-NEXT:    ret i32 [[ADD26:%.*]]
; CHECK:       for.body:
; CHECK-NEXT:    [[I_050:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD27:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    [[A_049:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD26]], [[FOR_BODY]] ]
; CHECK-NEXT:    [[ADD3:%.*]] = or i32 [[I_050]], 1
; CHECK-NEXT:    [[ADD11:%.*]] = or i32 [[I_050]], 2
; CHECK-NEXT:    [[ADD19:%.*]] = or i32 [[I_050]], 3
; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i16, ptr [[B:%.*]], i32 [[I_050]]
; CHECK-NEXT:    [[ARRAYIDX4:%.*]] = getelementptr inbounds i16, ptr [[B]], i32 [[ADD3]]
; CHECK-NEXT:    [[ARRAYIDX12:%.*]] = getelementptr inbounds i16, ptr [[B]], i32 [[ADD11]]
; CHECK-NEXT:    [[ARRAYIDX20:%.*]] = getelementptr inbounds i16, ptr [[B]], i32 [[ADD19]]
; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, ptr [[C:%.*]], i32 [[I_050]]
; CHECK-NEXT:    [[ARRAYIDX7:%.*]] = getelementptr inbounds i16, ptr [[C]], i32 [[ADD3]]
; CHECK-NEXT:    [[ARRAYIDX15:%.*]] = getelementptr inbounds i16, ptr [[C]], i32 [[ADD11]]
; CHECK-NEXT:    [[ARRAYIDX23:%.*]] = getelementptr inbounds i16, ptr [[C]], i32 [[ADD19]]
; CHECK-NEXT:    [[TMP:%.*]] = load i16, ptr [[ARRAYIDX]], align 2
; CHECK-NEXT:    [[TMP2:%.*]] = load i16, ptr [[ARRAYIDX4]], align 2
; CHECK-NEXT:    [[TMP4:%.*]] = load i16, ptr [[ARRAYIDX12]], align 2
; CHECK-NEXT:    [[TMP6:%.*]] = load i16, ptr [[ARRAYIDX20]], align 2
; CHECK-NEXT:    [[TMP1:%.*]] = load i16, ptr [[ARRAYIDX1]], align 2
; CHECK-NEXT:    store i16 43, ptr [[ARRAYIDX7]], align 2
; CHECK-NEXT:    [[TMP3:%.*]] = load i16, ptr [[ARRAYIDX7]], align 2
; CHECK-NEXT:    [[TMP5:%.*]] = load i16, ptr [[ARRAYIDX15]], align 2
; CHECK-NEXT:    [[TMP7:%.*]] = load i16, ptr [[ARRAYIDX23]], align 2
; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[TMP]] to i32
; CHECK-NEXT:    [[CONV2:%.*]] = sext i16 [[TMP1]] to i32
; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[CONV2]], [[CONV]]
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[MUL]], [[A_049]]
; CHECK-NEXT:    [[CONV5:%.*]] = sext i16 [[TMP2]] to i32
; CHECK-NEXT:    [[CONV8:%.*]] = sext i16 [[TMP3]] to i32
; CHECK-NEXT:    [[MUL9:%.*]] = mul nsw i32 [[CONV8]], [[CONV5]]
; CHECK-NEXT:    [[ADD10:%.*]] = add nsw i32 [[ADD]], [[MUL9]]
; CHECK-NEXT:    [[CONV13:%.*]] = sext i16 [[TMP4]] to i32
; CHECK-NEXT:    [[CONV16:%.*]] = sext i16 [[TMP5]] to i32
; CHECK-NEXT:    [[MUL17:%.*]] = mul nsw i32 [[CONV16]], [[CONV13]]
; CHECK-NEXT:    [[ADD18:%.*]] = add nsw i32 [[ADD10]], [[MUL17]]
; CHECK-NEXT:    [[CONV21:%.*]] = sext i16 [[TMP6]] to i32
; CHECK-NEXT:    [[CONV24:%.*]] = sext i16 [[TMP7]] to i32
; CHECK-NEXT:    [[MUL25:%.*]] = mul nsw i32 [[CONV24]], [[CONV21]]
; CHECK-NEXT:    [[ADD26]] = add nsw i32 [[ADD18]], [[MUL25]]
; CHECK-NEXT:    [[ADD27]] = add nuw nsw i32 [[I_050]], 4
; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD27]], 100
; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
;
entry:
  br label %for.body

for.cond.cleanup:                                 ; preds = %for.body
  ret i32 %add26

for.body:                                         ; preds = %for.body, %entry
  %i.050 = phi i32 [ 0, %entry ], [ %add27, %for.body ]
  %a.049 = phi i32 [ 0, %entry ], [ %add26, %for.body ]
  %add3 = or i32 %i.050, 1
  %add11 = or i32 %i.050, 2
  %add19 = or i32 %i.050, 3
  %arrayidx = getelementptr inbounds i16, ptr %b, i32 %i.050
  %arrayidx4 = getelementptr inbounds i16, ptr %b, i32 %add3
  %arrayidx12 = getelementptr inbounds i16, ptr %b, i32 %add11
  %arrayidx20 = getelementptr inbounds i16, ptr %b, i32 %add19
  %arrayidx1 = getelementptr inbounds i16, ptr %c, i32 %i.050
  %arrayidx7 = getelementptr inbounds i16, ptr %c, i32 %add3
  %arrayidx15 = getelementptr inbounds i16, ptr %c, i32 %add11
  %arrayidx23 = getelementptr inbounds i16, ptr %c, i32 %add19
  %tmp = load i16, ptr %arrayidx, align 2
  %tmp2 = load i16, ptr %arrayidx4, align 2
  %tmp4 = load i16, ptr %arrayidx12, align 2
  %tmp6 = load i16, ptr %arrayidx20, align 2
  %tmp1 = load i16, ptr %arrayidx1, align 2
  store i16 43, ptr %arrayidx7
  %tmp3 = load i16, ptr %arrayidx7, align 2
  %tmp5 = load i16, ptr %arrayidx15, align 2
  %tmp7 = load i16, ptr %arrayidx23, align 2
  %conv = sext i16 %tmp to i32
  %conv2 = sext i16 %tmp1 to i32
  %mul = mul nsw i32 %conv2, %conv
  %add = add nsw i32 %mul, %a.049
  %conv5 = sext i16 %tmp2 to i32
  %conv8 = sext i16 %tmp3 to i32
  %mul9 = mul nsw i32 %conv8, %conv5
  %add10 = add nsw i32 %add, %mul9
  %conv13 = sext i16 %tmp4 to i32
  %conv16 = sext i16 %tmp5 to i32
  %mul17 = mul nsw i32 %conv16, %conv13
  %add18 = add nsw i32 %add10, %mul17
  %conv21 = sext i16 %tmp6 to i32
  %conv24 = sext i16 %tmp7 to i32
  %mul25 = mul nsw i32 %conv24, %conv21
  %add26 = add nsw i32 %add18, %mul25
  %add27 = add nuw nsw i32 %i.050, 4
  %cmp = icmp ult i32 %add27, 100
  br i1 %cmp, label %for.body, label %for.cond.cleanup
}

