; 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 }