|  | ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 | 
|  | ; RUN: opt < %s -passes=infer-alignment -S | FileCheck %s | 
|  |  | 
|  | ; ------------------------------------------------------------------------------ | 
|  | ; Simple test | 
|  | ; ------------------------------------------------------------------------------ | 
|  |  | 
|  | define void @simple_forwardpropagate(ptr %a) { | 
|  | ; CHECK-LABEL: define void @simple_forwardpropagate | 
|  | ; CHECK-SAME: (ptr [[A:%.*]]) { | 
|  | ; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A]] to i64 | 
|  | ; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 | 
|  | ; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]]) | 
|  | ; CHECK-NEXT:    [[LOAD_A:%.*]] = load i32, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    store i32 345, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | %ptrint = ptrtoint ptr %a to i64 | 
|  | %maskedptr = and i64 %ptrint, 31 | 
|  | %maskcond = icmp eq i64 %maskedptr, 0 | 
|  | tail call void @llvm.assume(i1 %maskcond) | 
|  |  | 
|  | %load.a = load i32, ptr %a, align 4 | 
|  | store i32 345, ptr %a, align 4 | 
|  |  | 
|  | ret void | 
|  | } | 
|  |  | 
|  | define void @simple_backpropagate(ptr %a) { | 
|  | ; CHECK-LABEL: define void @simple_backpropagate | 
|  | ; CHECK-SAME: (ptr [[A:%.*]]) { | 
|  | ; CHECK-NEXT:    [[LOAD_A:%.*]] = load i32, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    store i32 345, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A]] to i64 | 
|  | ; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 | 
|  | ; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]]) | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | %load.a = load i32, ptr %a, align 4 | 
|  | store i32 345, ptr %a, align 4 | 
|  |  | 
|  | %ptrint = ptrtoint ptr %a to i64 | 
|  | %maskedptr = and i64 %ptrint, 31 | 
|  | %maskcond = icmp eq i64 %maskedptr, 0 | 
|  | tail call void @llvm.assume(i1 %maskcond) | 
|  |  | 
|  | ret void | 
|  | } | 
|  |  | 
|  | define void @simple_forwardpropagate_bundle(ptr %a) { | 
|  | ; CHECK-LABEL: define void @simple_forwardpropagate_bundle | 
|  | ; CHECK-SAME: (ptr [[A:%.*]]) { | 
|  | ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i32 32) ] | 
|  | ; CHECK-NEXT:    [[LOAD_A:%.*]] = load i32, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    store i32 345, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32)] | 
|  | %load.a = load i32, ptr %a, align 4 | 
|  | store i32 345, ptr %a, align 4 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | define void @simple_backpropagate_bundle(ptr %a) { | 
|  | ; CHECK-LABEL: define void @simple_backpropagate_bundle | 
|  | ; CHECK-SAME: (ptr [[A:%.*]]) { | 
|  | ; CHECK-NEXT:    [[LOAD_A:%.*]] = load i32, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    store i32 345, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i32 32) ] | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | %load.a = load i32, ptr %a, align 4 | 
|  | store i32 345, ptr %a, align 4 | 
|  | call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32)] | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; ------------------------------------------------------------------------------ | 
|  | ; Complex test | 
|  | ; ------------------------------------------------------------------------------ | 
|  |  | 
|  | define void @loop_forwardpropagate(ptr %a, ptr %b) { | 
|  | ; CHECK-LABEL: define void @loop_forwardpropagate | 
|  | ; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]]) { | 
|  | ; CHECK-NEXT:  entry: | 
|  | ; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A]] to i64 | 
|  | ; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63 | 
|  | ; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]]) | 
|  | ; CHECK-NEXT:    [[PTRINT2:%.*]] = ptrtoint ptr [[B]] to i64 | 
|  | ; CHECK-NEXT:    [[MASKEDPTR2:%.*]] = and i64 [[PTRINT2]], 63 | 
|  | ; CHECK-NEXT:    [[MASKEDCOND2:%.*]] = icmp eq i64 [[MASKEDPTR2]], 0 | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKEDCOND2]]) | 
|  | ; CHECK-NEXT:    br label [[FOR_BODY:%.*]] | 
|  | ; CHECK:       for.body: | 
|  | ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[FOR_BODY]] ] | 
|  | ; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[I]] | 
|  | ; CHECK-NEXT:    [[LOAD_B:%.*]] = load i32, ptr [[GEP_B]], align 64 | 
|  | ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[LOAD_B]], 1 | 
|  | ; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I]] | 
|  | ; CHECK-NEXT:    store i32 [[ADD]], ptr [[GEP_A]], align 64 | 
|  | ; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 16 | 
|  | ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[I_NEXT]], 1648 | 
|  | ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] | 
|  | ; CHECK:       for.end: | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | entry: | 
|  | %ptrint = ptrtoint ptr %a to i64 | 
|  | %maskedptr = and i64 %ptrint, 63 | 
|  | %maskcond = icmp eq i64 %maskedptr, 0 | 
|  | tail call void @llvm.assume(i1 %maskcond) | 
|  |  | 
|  | %ptrint2 = ptrtoint ptr %b to i64 | 
|  | %maskedptr2 = and i64 %ptrint2, 63 | 
|  | %maskedcond2 = icmp eq i64 %maskedptr2, 0 | 
|  | tail call void @llvm.assume(i1 %maskedcond2) | 
|  |  | 
|  | br label %for.body | 
|  |  | 
|  | for.body: | 
|  | %i = phi i64 [ 0, %entry ], [ %i.next, %for.body ] | 
|  |  | 
|  | %gep.b = getelementptr inbounds i32, ptr %b, i64 %i | 
|  | %load.b = load i32, ptr %gep.b, align 4 | 
|  | %add = add nsw i32 %load.b, 1 | 
|  |  | 
|  | %gep.a = getelementptr inbounds i32, ptr %a, i64 %i | 
|  | store i32 %add, ptr %gep.a, align 4 | 
|  |  | 
|  | %i.next = add nuw nsw i64 %i, 16 | 
|  | %cmp = icmp slt i64 %i.next, 1648 | 
|  |  | 
|  | br i1 %cmp, label %for.body, label %for.end | 
|  |  | 
|  | for.end: | 
|  | ret void | 
|  | } | 
|  |  | 
|  | define void @loop_forwardpropagate_bundle(ptr %a, ptr %b) { | 
|  | ; CHECK-LABEL: define void @loop_forwardpropagate_bundle | 
|  | ; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]]) { | 
|  | ; CHECK-NEXT:  entry: | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i32 64) ] | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 true) [ "align"(ptr [[B]], i32 64) ] | 
|  | ; CHECK-NEXT:    br label [[FOR_BODY:%.*]] | 
|  | ; CHECK:       for.body: | 
|  | ; CHECK-NEXT:    [[I:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[FOR_BODY]] ] | 
|  | ; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[I]] | 
|  | ; CHECK-NEXT:    [[LOAD_B:%.*]] = load i32, ptr [[GEP_B]], align 64 | 
|  | ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[LOAD_B]], 1 | 
|  | ; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I]] | 
|  | ; CHECK-NEXT:    store i32 [[ADD]], ptr [[GEP_A]], align 64 | 
|  | ; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 16 | 
|  | ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[I_NEXT]], 1648 | 
|  | ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] | 
|  | ; CHECK:       for.end: | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | entry: | 
|  | tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 64)] | 
|  | tail call void @llvm.assume(i1 true) ["align"(ptr %b, i32 64)] | 
|  | br label %for.body | 
|  |  | 
|  | for.body: | 
|  | %i = phi i64 [ 0, %entry ], [ %i.next, %for.body ] | 
|  |  | 
|  | %gep.b = getelementptr inbounds i32, ptr %b, i64 %i | 
|  | %load.b = load i32, ptr %gep.b, align 4 | 
|  | %add = add nsw i32 %load.b, 1 | 
|  |  | 
|  | %gep.a = getelementptr inbounds i32, ptr %a, i64 %i | 
|  | store i32 %add, ptr %gep.a, align 4 | 
|  |  | 
|  | %i.next = add nuw nsw i64 %i, 16 | 
|  | %cmp = icmp slt i64 %i.next, 1648 | 
|  |  | 
|  | br i1 %cmp, label %for.body, label %for.end | 
|  |  | 
|  | for.end: | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; Check that assume is propagated backwards through all | 
|  | ; operations that are `isGuaranteedToTransferExecutionToSuccessor` | 
|  | ; (it should reach the load and mark it as `align 32`). | 
|  | define void @complex_backpropagate(ptr %a, ptr %b, ptr %c) { | 
|  | ; CHECK-LABEL: define void @complex_backpropagate | 
|  | ; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) { | 
|  | ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8 | 
|  | ; CHECK-NEXT:    [[LOAD_A:%.*]] = load i32, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    [[LOAD_B:%.*]] = load i32, ptr [[B]], align 4 | 
|  | ; CHECK-NEXT:    store i32 [[LOAD_B]], ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    [[OBJ_SIZE:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr [[C]], i1 false, i1 false, i1 false) | 
|  | ; CHECK-NEXT:    store i64 [[OBJ_SIZE]], ptr [[ALLOCA]], align 8 | 
|  | ; CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint ptr [[A]] to i64 | 
|  | ; CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 | 
|  | ; CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 [[MASKCOND]]) | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | %alloca = alloca i64 | 
|  | %load.a = load i32, ptr %a, align 4 | 
|  |  | 
|  | %load.b = load i32, ptr %b | 
|  | store i32 %load.b, ptr %a | 
|  |  | 
|  | %obj.size = call i64 @llvm.objectsize.i64.p0(ptr %c, i1 false) | 
|  | store i64 %obj.size, ptr %alloca | 
|  |  | 
|  | %ptrint = ptrtoint ptr %a to i64 | 
|  | %maskedptr = and i64 %ptrint, 31 | 
|  | %maskcond = icmp eq i64 %maskedptr, 0 | 
|  | tail call void @llvm.assume(i1 %maskcond) | 
|  |  | 
|  | ret void | 
|  | } | 
|  |  | 
|  | define void @complex_backpropagate_bundle(ptr %a, ptr %b, ptr %c) { | 
|  | ; CHECK-LABEL: define void @complex_backpropagate_bundle | 
|  | ; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) { | 
|  | ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8 | 
|  | ; CHECK-NEXT:    [[LOAD_A:%.*]] = load i32, ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    [[LOAD_B:%.*]] = load i32, ptr [[B]], align 4 | 
|  | ; CHECK-NEXT:    store i32 [[LOAD_B]], ptr [[A]], align 32 | 
|  | ; CHECK-NEXT:    [[OBJ_SIZE:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr [[C]], i1 false, i1 false, i1 false) | 
|  | ; CHECK-NEXT:    store i64 [[OBJ_SIZE]], ptr [[ALLOCA]], align 8 | 
|  | ; CHECK-NEXT:    tail call void @llvm.assume(i1 true) [ "align"(ptr [[A]], i32 32) ] | 
|  | ; CHECK-NEXT:    ret void | 
|  | ; | 
|  | %alloca = alloca i64 | 
|  | %load.a = load i32, ptr %a, align 4 | 
|  |  | 
|  | %load.b = load i32, ptr %b | 
|  | store i32 %load.b, ptr %a | 
|  |  | 
|  | %obj.size = call i64 @llvm.objectsize.i64.p0(ptr %c, i1 false) | 
|  | store i64 %obj.size, ptr %alloca | 
|  |  | 
|  | tail call void @llvm.assume(i1 true) ["align"(ptr %a, i32 32)] | 
|  |  | 
|  | ret void | 
|  | } | 
|  |  | 
|  | declare i64 @llvm.objectsize.i64.p0(ptr, i1) | 
|  | declare void @llvm.assume(i1) |