; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -passes='require,gvn' -S < %s | FileCheck %s --check-prefixes=CHECK-MEMDEP ; RUN: opt -passes='require,gvn' -S < %s | FileCheck %s --check-prefixes=CHECK-MEMSSA declare noalias ptr @malloc(i64) ; Detecting that %s is fully redundant should let us detect that %w is partially ; redundant. define void @fn1(ptr noalias %start, ptr %width, i32 %h) { ; CHECK-MEMDEP-LABEL: define void @fn1( ; CHECK-MEMDEP-SAME: ptr noalias [[START:%.*]], ptr [[WIDTH:%.*]], i32 [[H:%.*]]) { ; CHECK-MEMDEP-NEXT: [[ENTRY:.*:]] ; CHECK-MEMDEP-NEXT: [[CALL:%.*]] = tail call noalias ptr @malloc(i64 1024) ; CHECK-MEMDEP-NEXT: store ptr [[CALL]], ptr [[START]], align 8 ; CHECK-MEMDEP-NEXT: br label %[[PREHEADER:.*]] ; CHECK-MEMDEP: [[PREHEADER]]: ; CHECK-MEMDEP-NEXT: [[CMP:%.*]] = icmp slt i32 1, [[H]] ; CHECK-MEMDEP-NEXT: br i1 [[CMP]], label %[[PREHEADER_BODY_CRIT_EDGE:.*]], label %[[EXIT:.*]] ; CHECK-MEMDEP: [[PREHEADER_BODY_CRIT_EDGE]]: ; CHECK-MEMDEP-NEXT: [[W_PRE:%.*]] = load i32, ptr [[WIDTH]], align 8 ; CHECK-MEMDEP-NEXT: br label %[[BODY:.*]] ; CHECK-MEMDEP: [[BODY]]: ; CHECK-MEMDEP-NEXT: [[J:%.*]] = phi i32 [ 0, %[[PREHEADER_BODY_CRIT_EDGE]] ], [ [[J_NEXT:%.*]], %[[BODY]] ] ; CHECK-MEMDEP-NEXT: store i32 0, ptr [[CALL]], align 4 ; CHECK-MEMDEP-NEXT: [[J_NEXT]] = add nuw nsw i32 [[J]], 1 ; CHECK-MEMDEP-NEXT: [[CMP3:%.*]] = icmp slt i32 [[J_NEXT]], [[W_PRE]] ; CHECK-MEMDEP-NEXT: br i1 [[CMP3]], label %[[BODY]], label %[[PREHEADER]] ; CHECK-MEMDEP: [[EXIT]]: ; CHECK-MEMDEP-NEXT: ret void ; ; CHECK-MEMSSA-LABEL: define void @fn1( ; CHECK-MEMSSA-SAME: ptr noalias [[START:%.*]], ptr [[WIDTH:%.*]], i32 [[H:%.*]]) { ; CHECK-MEMSSA-NEXT: [[ENTRY:.*:]] ; CHECK-MEMSSA-NEXT: [[CALL:%.*]] = tail call noalias ptr @malloc(i64 1024) ; CHECK-MEMSSA-NEXT: store ptr [[CALL]], ptr [[START]], align 8 ; CHECK-MEMSSA-NEXT: br label %[[PREHEADER:.*]] ; CHECK-MEMSSA: [[PREHEADER]]: ; CHECK-MEMSSA-NEXT: [[CMP:%.*]] = icmp slt i32 1, [[H]] ; CHECK-MEMSSA-NEXT: br i1 [[CMP]], label %[[BODY:.*]], label %[[EXIT:.*]] ; CHECK-MEMSSA: [[BODY]]: ; CHECK-MEMSSA-NEXT: [[J:%.*]] = phi i32 [ 0, %[[PREHEADER]] ], [ [[J_NEXT:%.*]], %[[BODY]] ] ; CHECK-MEMSSA-NEXT: [[S:%.*]] = load ptr, ptr [[START]], align 8 ; CHECK-MEMSSA-NEXT: store i32 0, ptr [[S]], align 4 ; CHECK-MEMSSA-NEXT: [[J_NEXT]] = add nuw nsw i32 [[J]], 1 ; CHECK-MEMSSA-NEXT: [[W:%.*]] = load i32, ptr [[WIDTH]], align 8 ; CHECK-MEMSSA-NEXT: [[CMP3:%.*]] = icmp slt i32 [[J_NEXT]], [[W]] ; CHECK-MEMSSA-NEXT: br i1 [[CMP3]], label %[[BODY]], label %[[PREHEADER]] ; CHECK-MEMSSA: [[EXIT]]: ; CHECK-MEMSSA-NEXT: ret void ; entry: %call = tail call noalias ptr @malloc(i64 1024) store ptr %call, ptr %start, align 8 br label %preheader preheader: %cmp = icmp slt i32 1, %h br i1 %cmp, label %body, label %exit body: %j = phi i32 [ 0, %preheader ], [ %j.next, %body ] %s = load ptr, ptr %start, align 8 store i32 0, ptr %s, align 4 %j.next = add nuw nsw i32 %j, 1 %w = load i32, ptr %width, align 8 %cmp3 = icmp slt i32 %j.next, %w br i1 %cmp3, label %body, label %preheader exit: ret void } ; %s is fully redundant but has more than one available value. Detecting that ; %w is partially redundant requires alias analysis that can analyze those ; values. define void @fn2(ptr noalias %start, ptr %width, i32 %h, i32 %arg) { ; CHECK-MEMDEP-LABEL: define void @fn2( ; CHECK-MEMDEP-SAME: ptr noalias [[START:%.*]], ptr [[WIDTH:%.*]], i32 [[H:%.*]], i32 [[ARG:%.*]]) { ; CHECK-MEMDEP-NEXT: [[ENTRY:.*:]] ; CHECK-MEMDEP-NEXT: [[CALL:%.*]] = tail call noalias ptr @malloc(i64 1024) ; CHECK-MEMDEP-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ARG]], 0 ; CHECK-MEMDEP-NEXT: br i1 [[CMP1]], label %[[IF:.*]], label %[[ELSE:.*]] ; CHECK-MEMDEP: [[IF]]: ; CHECK-MEMDEP-NEXT: store ptr [[CALL]], ptr [[START]], align 8 ; CHECK-MEMDEP-NEXT: br label %[[PREHEADER:.*]] ; CHECK-MEMDEP: [[ELSE]]: ; CHECK-MEMDEP-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[CALL]], i32 [[ARG]] ; CHECK-MEMDEP-NEXT: store ptr [[GEP]], ptr [[START]], align 8 ; CHECK-MEMDEP-NEXT: br label %[[PREHEADER]] ; CHECK-MEMDEP: [[PREHEADER]]: ; CHECK-MEMDEP-NEXT: [[S:%.*]] = phi ptr [ [[S]], %[[BODY:.*]] ], [ [[GEP]], %[[ELSE]] ], [ [[CALL]], %[[IF]] ] ; CHECK-MEMDEP-NEXT: [[CMP:%.*]] = icmp slt i32 1, [[H]] ; CHECK-MEMDEP-NEXT: br i1 [[CMP]], label %[[PREHEADER_BODY_CRIT_EDGE:.*]], label %[[EXIT:.*]] ; CHECK-MEMDEP: [[PREHEADER_BODY_CRIT_EDGE]]: ; CHECK-MEMDEP-NEXT: [[W_PRE:%.*]] = load i32, ptr [[WIDTH]], align 8 ; CHECK-MEMDEP-NEXT: br label %[[BODY]] ; CHECK-MEMDEP: [[BODY]]: ; CHECK-MEMDEP-NEXT: [[J:%.*]] = phi i32 [ 0, %[[PREHEADER_BODY_CRIT_EDGE]] ], [ [[J_NEXT:%.*]], %[[BODY]] ] ; CHECK-MEMDEP-NEXT: store i32 0, ptr [[S]], align 4 ; CHECK-MEMDEP-NEXT: [[J_NEXT]] = add nuw nsw i32 [[J]], 1 ; CHECK-MEMDEP-NEXT: [[CMP3:%.*]] = icmp slt i32 [[J_NEXT]], [[W_PRE]] ; CHECK-MEMDEP-NEXT: br i1 [[CMP3]], label %[[BODY]], label %[[PREHEADER]] ; CHECK-MEMDEP: [[EXIT]]: ; CHECK-MEMDEP-NEXT: ret void ; ; CHECK-MEMSSA-LABEL: define void @fn2( ; CHECK-MEMSSA-SAME: ptr noalias [[START:%.*]], ptr [[WIDTH:%.*]], i32 [[H:%.*]], i32 [[ARG:%.*]]) { ; CHECK-MEMSSA-NEXT: [[ENTRY:.*:]] ; CHECK-MEMSSA-NEXT: [[CALL:%.*]] = tail call noalias ptr @malloc(i64 1024) ; CHECK-MEMSSA-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ARG]], 0 ; CHECK-MEMSSA-NEXT: br i1 [[CMP1]], label %[[IF:.*]], label %[[ELSE:.*]] ; CHECK-MEMSSA: [[IF]]: ; CHECK-MEMSSA-NEXT: store ptr [[CALL]], ptr [[START]], align 8 ; CHECK-MEMSSA-NEXT: br label %[[PREHEADER:.*]] ; CHECK-MEMSSA: [[ELSE]]: ; CHECK-MEMSSA-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[CALL]], i32 [[ARG]] ; CHECK-MEMSSA-NEXT: store ptr [[GEP]], ptr [[START]], align 8 ; CHECK-MEMSSA-NEXT: br label %[[PREHEADER]] ; CHECK-MEMSSA: [[PREHEADER]]: ; CHECK-MEMSSA-NEXT: [[CMP:%.*]] = icmp slt i32 1, [[H]] ; CHECK-MEMSSA-NEXT: br i1 [[CMP]], label %[[BODY:.*]], label %[[EXIT:.*]] ; CHECK-MEMSSA: [[BODY]]: ; CHECK-MEMSSA-NEXT: [[J:%.*]] = phi i32 [ 0, %[[PREHEADER]] ], [ [[J_NEXT:%.*]], %[[BODY]] ] ; CHECK-MEMSSA-NEXT: [[S:%.*]] = load ptr, ptr [[START]], align 8 ; CHECK-MEMSSA-NEXT: store i32 0, ptr [[S]], align 4 ; CHECK-MEMSSA-NEXT: [[J_NEXT]] = add nuw nsw i32 [[J]], 1 ; CHECK-MEMSSA-NEXT: [[W:%.*]] = load i32, ptr [[WIDTH]], align 8 ; CHECK-MEMSSA-NEXT: [[CMP3:%.*]] = icmp slt i32 [[J_NEXT]], [[W]] ; CHECK-MEMSSA-NEXT: br i1 [[CMP3]], label %[[BODY]], label %[[PREHEADER]] ; CHECK-MEMSSA: [[EXIT]]: ; CHECK-MEMSSA-NEXT: ret void ; entry: %call = tail call noalias ptr @malloc(i64 1024) %cmp1 = icmp slt i32 %arg, 0 br i1 %cmp1, label %if, label %else if: store ptr %call, ptr %start, align 8 br label %preheader else: %gep = getelementptr inbounds i32, ptr %call, i32 %arg store ptr %gep, ptr %start, align 8 br label %preheader preheader: %cmp = icmp slt i32 1, %h br i1 %cmp, label %body, label %exit body: %j = phi i32 [ 0, %preheader ], [ %j.next, %body ] %s = load ptr, ptr %start, align 8 store i32 0, ptr %s, align 4 %j.next = add nuw nsw i32 %j, 1 %w = load i32, ptr %width, align 8 %cmp3 = icmp slt i32 %j.next, %w br i1 %cmp3, label %body, label %preheader exit: ret void }