From 04f61fb73dc6a994ab267d431f2fdaedc67430ff Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 24 Mar 2023 15:24:21 +0100 Subject: [PATCH] [LICM] Add tests for GEP reassociation (NFC) --- llvm/test/Transforms/LICM/gep-reassociate.ll | 333 +++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 llvm/test/Transforms/LICM/gep-reassociate.ll diff --git a/llvm/test/Transforms/LICM/gep-reassociate.ll b/llvm/test/Transforms/LICM/gep-reassociate.ll new file mode 100644 index 0000000..4283eb1 --- /dev/null +++ b/llvm/test/Transforms/LICM/gep-reassociate.ll @@ -0,0 +1,333 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 +; RUN: opt -S -passes=licm < %s | FileCheck %s + +declare void @use(ptr) +declare i32 @get.i32() +declare i64 @get.i64() +declare ptr @get.ptr() + +define void @only_one_inbounds(ptr %ptr, i1 %c, i32 %arg) { +; CHECK-LABEL: define void @only_one_inbounds +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i32 [[ARG:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARG_EXT:%.*]] = zext i32 [[ARG]] to i64 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL:%.*]] = call i32 @get.i32() +; CHECK-NEXT: [[VAL_EXT:%.*]] = zext i32 [[VAL]] to i64 +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[VAL_EXT]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[ARG_EXT]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + %arg.ext = zext i32 %arg to i64 + br label %loop + +loop: + %val = call i32 @get.i32() + %val.ext = zext i32 %val to i64 + %ptr2 = getelementptr inbounds i8, ptr %ptr, i64 %val.ext + %ptr3 = getelementptr i8, ptr %ptr2, i64 %arg.ext + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @both_inbounds_one_neg(ptr %ptr, i1 %c) { +; CHECK-LABEL: define void @both_inbounds_one_neg +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL:%.*]] = call i32 @get.i32() +; CHECK-NEXT: [[VAL_EXT:%.*]] = zext i32 [[VAL]] to i64 +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[VAL_EXT]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 -1 +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val = call i32 @get.i32() + %val.ext = zext i32 %val to i64 + %ptr2 = getelementptr inbounds i8, ptr %ptr, i64 %val.ext + %ptr3 = getelementptr i8, ptr %ptr2, i64 -1 + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @both_inbounds_pos(ptr %ptr, i1 %c) { +; CHECK-LABEL: define void @both_inbounds_pos +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL:%.*]] = call i32 @get.i32() +; CHECK-NEXT: [[VAL_EXT:%.*]] = zext i32 [[VAL]] to i64 +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[VAL_EXT]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr inbounds i8, ptr [[PTR2]], i64 1 +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val = call i32 @get.i32() + %val.ext = zext i32 %val to i64 + %ptr2 = getelementptr inbounds i8, ptr %ptr, i64 %val.ext + %ptr3 = getelementptr inbounds i8, ptr %ptr2, i64 1 + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @different_elem_types(ptr %ptr, i1 %c, i64 %arg) { +; CHECK-LABEL: define void @different_elem_types +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i64 [[ARG:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[VAL]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i64, ptr [[PTR2]], i64 [[ARG]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val = call i64 @get.i64() + %ptr2 = getelementptr i32, ptr %ptr, i64 %val + %ptr3 = getelementptr i64, ptr %ptr2, i64 %arg + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @src_has_extra_use(ptr %ptr, i1 %c, i64 %arg) { +; CHECK-LABEL: define void @src_has_extra_use +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i64 [[ARG:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[VAL]] +; CHECK-NEXT: call void @use(ptr [[PTR2]]) +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[ARG]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val = call i64 @get.i64() + %ptr2 = getelementptr i8, ptr %ptr, i64 %val + call void @use(ptr %ptr2) + %ptr3 = getelementptr i8, ptr %ptr2, i64 %arg + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @src_already_invariant(ptr %ptr, i1 %c, i64 %arg1, i64 %arg2) { +; CHECK-LABEL: define void @src_already_invariant +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i64 [[ARG1:%.*]], i64 [[ARG2:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[ARG1]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[ARG2]] +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %ptr2 = getelementptr i8, ptr %ptr, i64 %arg1 + %ptr3 = getelementptr i8, ptr %ptr2, i64 %arg2 + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @gep_idx_not_invariant(ptr %ptr, i1 %c) { +; CHECK-LABEL: define void @gep_idx_not_invariant +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL1:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[VAL2:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[VAL1]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[VAL2]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val1 = call i64 @get.i64() + %val2 = call i64 @get.i64() + %ptr2 = getelementptr i8, ptr %ptr, i64 %val1 + %ptr3 = getelementptr i8, ptr %ptr2, i64 %val2 + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @src_ptr_not_invariant(i1 %c, i64 %arg) { +; CHECK-LABEL: define void @src_ptr_not_invariant +; CHECK-SAME: (i1 [[C:%.*]], i64 [[ARG:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[PTR:%.*]] = call ptr @get.ptr() +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[ARG]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[VAL]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val = call i64 @get.i64() + %ptr = call ptr @get.ptr() + %ptr2 = getelementptr i8, ptr %ptr, i64 %arg + %ptr3 = getelementptr i8, ptr %ptr2, i64 %val + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @multiple_indices(ptr %ptr, i1 %c, i64 %arg1, i64 %arg2) { +; CHECK-LABEL: define void @multiple_indices +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i64 [[ARG1:%.*]], i64 [[ARG2:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL1:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[VAL2:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr [0 x i8], ptr [[PTR]], i64 [[VAL1]], i64 [[VAL2]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr [0 x i8], ptr [[PTR2]], i64 [[ARG1]], i64 [[ARG2]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val1 = call i64 @get.i64() + %val2 = call i64 @get.i64() + %ptr2 = getelementptr [0 x i8], ptr %ptr, i64 %val1, i64 %val2 + %ptr3 = getelementptr [0 x i8], ptr %ptr2, i64 %arg1, i64 %arg2 + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @multiple_indices_not_invariant(ptr %ptr, i1 %c, i64 %arg1) { +; CHECK-LABEL: define void @multiple_indices_not_invariant +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i64 [[ARG1:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL1:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[VAL2:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[VAL3:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr [0 x i8], ptr [[PTR]], i64 [[VAL1]], i64 [[VAL2]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr [0 x i8], ptr [[PTR2]], i64 [[ARG1]], i64 [[VAL3]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val1 = call i64 @get.i64() + %val2 = call i64 @get.i64() + %val3 = call i64 @get.i64() + %ptr2 = getelementptr [0 x i8], ptr %ptr, i64 %val1, i64 %val2 + %ptr3 = getelementptr [0 x i8], ptr %ptr2, i64 %arg1, i64 %val3 + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} + +define void @multiple_indices_very_invariant(ptr %ptr, i1 %c, i64 %arg1, i64 %arg2, i64 %arg3) { +; CHECK-LABEL: define void @multiple_indices_very_invariant +; CHECK-SAME: (ptr [[PTR:%.*]], i1 [[C:%.*]], i64 [[ARG1:%.*]], i64 [[ARG2:%.*]], i64 [[ARG3:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[VAL1:%.*]] = call i64 @get.i64() +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr [0 x i8], ptr [[PTR]], i64 [[ARG3]], i64 [[VAL1]] +; CHECK-NEXT: [[PTR3:%.*]] = getelementptr [0 x i8], ptr [[PTR2]], i64 [[ARG1]], i64 [[ARG2]] +; CHECK-NEXT: call void @use(ptr [[PTR3]]) +; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + %val1 = call i64 @get.i64() + %ptr2 = getelementptr [0 x i8], ptr %ptr, i64 %arg3, i64 %val1 + %ptr3 = getelementptr [0 x i8], ptr %ptr2, i64 %arg1, i64 %arg2 + call void @use(ptr %ptr3) + br i1 %c, label %loop, label %exit + +exit: + ret void +} -- 2.7.4