| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -S --passes='simplifycfg<hoist-common-insts>' %s | FileCheck %s |
| |
| declare void @llvm.pseudoprobe(i64, i64, i32, i64) |
| |
| ; Check that instructions past the pseudoprobe instrs are still hoisted into the predecessor. |
| define void @hoist_loads_past_pseudoprobe(i1 %c, ptr %d, ptr %m, ptr %b, i32 %v) { |
| ; CHECK-LABEL: @hoist_loads_past_pseudoprobe( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 |
| ; CHECK-NEXT: [[CONV0:%.*]] = zext i16 [[TMP1]] to i32 |
| ; CHECK-NEXT: [[TMP3:%.*]] = load i16, ptr [[M1:%.*]], align 2 |
| ; CHECK-NEXT: [[CONV1:%.*]] = zext i16 [[TMP3]] to i32 |
| ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: call void @llvm.pseudoprobe(i64 1, i64 1, i32 0, i64 -1) |
| ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[CONV0]], [[V:%.*]] |
| ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ADD]], [[CONV1]] |
| ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[MUL]], 16 |
| ; CHECK-NEXT: [[CONV12:%.*]] = trunc i32 [[SHR]] to i16 |
| ; CHECK-NEXT: br label [[IF_END:%.*]] |
| ; CHECK: if.else: |
| ; CHECK-NEXT: call void @llvm.pseudoprobe(i64 1, i64 2, i32 0, i64 -1) |
| ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[CONV0]], [[V]] |
| ; CHECK-NEXT: [[MUL24:%.*]] = mul i32 [[SUB]], [[CONV1]] |
| ; CHECK-NEXT: [[SHR25:%.*]] = lshr i32 [[MUL24]], 16 |
| ; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[SHR25]] to i16 |
| ; CHECK-NEXT: [[CONV27:%.*]] = sub i16 0, [[TMP2]] |
| ; CHECK-NEXT: br label [[IF_END]] |
| ; CHECK: if.end: |
| ; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i16 [ [[CONV27]], [[IF_ELSE]] ], [ [[CONV12]], [[IF_THEN]] ] |
| ; CHECK-NEXT: store i16 [[STOREMERGE]], ptr [[D:%.*]], align 2 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br i1 %c, label %if.then, label %if.else |
| |
| if.then: |
| call void @llvm.pseudoprobe(i64 1, i64 1, i32 0, i64 -1) |
| %0 = load i16, ptr %b, align 2 |
| %conv0a = zext i16 %0 to i32 |
| %add = add i32 %conv0a, %v |
| %1 = load i16, ptr %m, align 2 |
| %conv1a = zext i16 %1 to i32 |
| %mul = mul i32 %add, %conv1a |
| %shr = lshr i32 %mul, 16 |
| %conv12 = trunc i32 %shr to i16 |
| br label %if.end |
| |
| if.else: |
| call void @llvm.pseudoprobe(i64 1, i64 2, i32 0, i64 -1) |
| %2 = load i16, ptr %b, align 2 |
| %conv0b = zext i16 %2 to i32 |
| %sub = sub i32 %conv0b, %v |
| %3 = load i16, ptr %m, align 2 |
| %conv1b = zext i16 %3 to i32 |
| %mul24 = mul i32 %sub, %conv1b |
| %shr25 = lshr i32 %mul24, 16 |
| %4 = trunc i32 %shr25 to i16 |
| %conv27 = sub i16 0, %4 |
| br label %if.end |
| |
| if.end: |
| %storemerge = phi i16 [ %conv27, %if.else ], [ %conv12, %if.then ] |
| store i16 %storemerge, ptr %d, align 2 |
| ret void |
| } |
| |
| ; Stores past pseudo probes are also hoisted into the predecessor. |
| define void @hoist_stores_past_pseudoprobe(i1 %c, ptr %d, ptr %d2, i32 %v) { |
| ; CHECK-LABEL: @hoist_stores_past_pseudoprobe( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: store i32 [[V:%.*]], ptr [[D:%.*]], align 4 |
| ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: call void @llvm.pseudoprobe(i64 2, i64 1, i32 0, i64 -1) |
| ; CHECK-NEXT: store i32 0, ptr [[D2:%.*]], align 4 |
| ; CHECK-NEXT: br label [[IF_END:%.*]] |
| ; CHECK: if.else: |
| ; CHECK-NEXT: call void @llvm.pseudoprobe(i64 2, i64 2, i32 0, i64 -1) |
| ; CHECK-NEXT: store i32 1, ptr [[D2]], align 4 |
| ; CHECK-NEXT: br label [[IF_END]] |
| ; CHECK: if.end: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br i1 %c, label %if.then, label %if.else |
| |
| if.then: |
| call void @llvm.pseudoprobe(i64 2, i64 1, i32 0, i64 -1) |
| store i32 %v, ptr %d, align 4 |
| store i32 0, ptr %d2, align 4 |
| br label %if.end |
| |
| if.else: |
| call void @llvm.pseudoprobe(i64 2, i64 2, i32 0, i64 -1) |
| store i32 %v, ptr %d, align 4 |
| store i32 1, ptr %d2, align 4 |
| br label %if.end |
| |
| if.end: |
| ret void |
| } |
| |
| declare ptr @callee(ptr, i32, i32) |
| |
| define ptr @dont_hoist_musttail_past_pseudoprobe(ptr %a, i32 %b, i32 %c) { |
| ; CHECK-LABEL: @dont_hoist_musttail_past_pseudoprobe( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[C:%.*]], 0 |
| ; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: call void @llvm.pseudoprobe(i64 3, i64 1, i32 0, i64 -1) |
| ; CHECK-NEXT: [[CALL:%.*]] = musttail call ptr @callee(ptr [[A:%.*]], i32 [[B:%.*]], i32 [[C]]) |
| ; CHECK-NEXT: ret ptr [[CALL]] |
| ; CHECK: if.else: |
| ; CHECK-NEXT: call void @llvm.pseudoprobe(i64 3, i64 2, i32 0, i64 -1) |
| ; CHECK-NEXT: [[CALL2:%.*]] = musttail call ptr @callee(ptr [[A]], i32 [[B]], i32 [[C]]) |
| ; CHECK-NEXT: ret ptr [[CALL2]] |
| ; |
| entry: |
| %cond = icmp eq i32 %c, 0 |
| br i1 %cond, label %if.then, label %if.else |
| |
| if.then: |
| call void @llvm.pseudoprobe(i64 3, i64 1, i32 0, i64 -1) |
| %call = musttail call ptr @callee(ptr %a, i32 %b, i32 %c) |
| ret ptr %call |
| |
| if.else: |
| call void @llvm.pseudoprobe(i64 3, i64 2, i32 0, i64 -1) |
| %call2 = musttail call ptr @callee(ptr %a, i32 %b, i32 %c) |
| ret ptr %call2 |
| } |