diff --git a/test/Transforms/InstCombine/multi-use-load-casts.ll b/test/Transforms/InstCombine/multi-use-load-casts.ll new file mode 100644 index 00000000000..147d893e285 --- /dev/null +++ b/test/Transforms/InstCombine/multi-use-load-casts.ll @@ -0,0 +1,153 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine < %s | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +; Positive test - all uses are identical casts. +define void @t0(i1 zeroext %c0, i1 zeroext %c1, i64* nocapture readonly %src) { +; CHECK-LABEL: @t0( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[DATA:%.*]] = load i64, i64* [[SRC:%.*]], align 8 +; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB3:%.*]], label [[BB7:%.*]] +; CHECK: bb3: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB4:%.*]], label [[BB5:%.*]] +; CHECK: bb4: +; CHECK-NEXT: tail call void @abort() +; CHECK-NEXT: unreachable +; CHECK: bb5: +; CHECK-NEXT: [[PTR0:%.*]] = inttoptr i64 [[DATA]] to i32* +; CHECK-NEXT: tail call void @sink0(i32* [[PTR0]]) +; CHECK-NEXT: br label [[BB9:%.*]] +; CHECK: bb7: +; CHECK-NEXT: [[PTR1:%.*]] = inttoptr i64 [[DATA]] to i32* +; CHECK-NEXT: tail call void @sink1(i32* [[PTR1]]) +; CHECK-NEXT: br label [[BB9]] +; CHECK: bb9: +; CHECK-NEXT: ret void +; +bb: + %data = load i64, i64* %src, align 8 + br i1 %c0, label %bb3, label %bb7 + +bb3: + br i1 %c1, label %bb4, label %bb5 + +bb4: + tail call void @abort() + unreachable + +bb5: + %ptr0 = inttoptr i64 %data to i32* + tail call void @sink0(i32* %ptr0) + br label %bb9 + +bb7: + %ptr1 = inttoptr i64 %data to i32* + tail call void @sink1(i32* %ptr1) + br label %bb9 + +bb9: + ret void +} + +; Negative test - all uses are casts, but non-identical ones. +define void @n1(i1 zeroext %c0, i1 zeroext %c1, i64* nocapture readonly %src) { +; CHECK-LABEL: @n1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[DATA:%.*]] = load i64, i64* [[SRC:%.*]], align 8 +; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB3:%.*]], label [[BB7:%.*]] +; CHECK: bb3: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB4:%.*]], label [[BB5:%.*]] +; CHECK: bb4: +; CHECK-NEXT: tail call void @abort() +; CHECK-NEXT: unreachable +; CHECK: bb5: +; CHECK-NEXT: [[PTR0:%.*]] = inttoptr i64 [[DATA]] to i32* +; CHECK-NEXT: tail call void @sink0(i32* [[PTR0]]) +; CHECK-NEXT: br label [[BB9:%.*]] +; CHECK: bb7: +; CHECK-NEXT: [[VEC:%.*]] = bitcast i64 [[DATA]] to <2 x i32> +; CHECK-NEXT: tail call void @sink2(<2 x i32> [[VEC]]) +; CHECK-NEXT: br label [[BB9]] +; CHECK: bb9: +; CHECK-NEXT: ret void +; +bb: + %data = load i64, i64* %src, align 8 + br i1 %c0, label %bb3, label %bb7 + +bb3: + br i1 %c1, label %bb4, label %bb5 + +bb4: + tail call void @abort() + unreachable + +bb5: + %ptr0 = inttoptr i64 %data to i32* + tail call void @sink0(i32* %ptr0) + br label %bb9 + +bb7: + %vec = bitcast i64 %data to <2 x i32> ; different cast + tail call void @sink2(<2 x i32> %vec) + br label %bb9 + +bb9: + ret void +} + +; Negative test - have non-cast users. +define void @n2(i1 zeroext %c0, i1 zeroext %c1, i64* nocapture readonly %src) { +; CHECK-LABEL: @n2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[DATA:%.*]] = load i64, i64* [[SRC:%.*]], align 8 +; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB3:%.*]], label [[BB7:%.*]] +; CHECK: bb3: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB4:%.*]], label [[BB5:%.*]] +; CHECK: bb4: +; CHECK-NEXT: tail call void @abort() +; CHECK-NEXT: unreachable +; CHECK: bb5: +; CHECK-NEXT: [[PTR0:%.*]] = inttoptr i64 [[DATA]] to i32* +; CHECK-NEXT: tail call void @sink0(i32* [[PTR0]]) +; CHECK-NEXT: br label [[BB9:%.*]] +; CHECK: bb7: +; CHECK-NEXT: tail call void @sink3(i64 [[DATA]]) +; CHECK-NEXT: br label [[BB9]] +; CHECK: bb9: +; CHECK-NEXT: ret void +; +bb: + %data = load i64, i64* %src, align 8 + br i1 %c0, label %bb3, label %bb7 + +bb3: + br i1 %c1, label %bb4, label %bb5 + +bb4: + tail call void @abort() + unreachable + +bb5: + %ptr0 = inttoptr i64 %data to i32* + tail call void @sink0(i32* %ptr0) + br label %bb9 + +bb7: + tail call void @sink3(i64 %data) ; non-cast use + br label %bb9 + +bb9: + ret void +} + +declare void @abort() + +declare void @sink0(i32*) + +declare void @sink1(i32*) + +declare void @sink2(<2 x i32>) + +declare void @sink3(i64)