GEPs are often in the form `gep [N x %T], ptr %p, i64 0, i64 %idx`. Canonicalize these to `gep %T, ptr %p, i64 %idx`. This enables transforms that only support one GEP index to work and improves CSE. Various transforms were recently hardened to make sure they still work without the leading index.
127 lines
4.1 KiB
LLVM
127 lines
4.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
|
|
target datalayout = "E-p:64:64:64-p1:64:64:64-p2:32:32:32-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
|
|
|
|
@x = external global <2 x i64>, align 16
|
|
@xx = external global [13 x <2 x i64>], align 16
|
|
|
|
@x.as2 = external addrspace(2) global <2 x i64>, align 16
|
|
|
|
define <2 x i64> @static_hem() {
|
|
; CHECK-LABEL: @static_hem(
|
|
; CHECK-NEXT: [[L:%.*]] = load <2 x i64>, ptr getelementptr (i8, ptr @x, i64 112), align 1
|
|
; CHECK-NEXT: ret <2 x i64> [[L]]
|
|
;
|
|
%t = getelementptr <2 x i64>, ptr @x, i32 7
|
|
%l = load <2 x i64>, ptr %t, align 1
|
|
ret <2 x i64> %l
|
|
}
|
|
|
|
define <2 x i64> @hem(i32 %i) {
|
|
; CHECK-LABEL: @hem(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I:%.*]] to i64
|
|
; CHECK-NEXT: [[T:%.*]] = getelementptr <2 x i64>, ptr @x, i64 [[TMP1]]
|
|
; CHECK-NEXT: [[L:%.*]] = load <2 x i64>, ptr [[T]], align 1
|
|
; CHECK-NEXT: ret <2 x i64> [[L]]
|
|
;
|
|
%t = getelementptr <2 x i64>, ptr @x, i32 %i
|
|
%l = load <2 x i64>, ptr %t, align 1
|
|
ret <2 x i64> %l
|
|
}
|
|
|
|
define <2 x i64> @hem_2d(i32 %i, i32 %j) {
|
|
; CHECK-LABEL: @hem_2d(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I:%.*]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[J:%.*]] to i64
|
|
; CHECK-NEXT: [[T_SPLIT:%.*]] = getelementptr [13 x <2 x i64>], ptr @xx, i64 [[TMP1]]
|
|
; CHECK-NEXT: [[T:%.*]] = getelementptr <2 x i64>, ptr [[T_SPLIT]], i64 [[TMP2]]
|
|
; CHECK-NEXT: [[L:%.*]] = load <2 x i64>, ptr [[T]], align 1
|
|
; CHECK-NEXT: ret <2 x i64> [[L]]
|
|
;
|
|
%t = getelementptr [13 x <2 x i64>], ptr @xx, i32 %i, i32 %j
|
|
%l = load <2 x i64>, ptr %t, align 1
|
|
ret <2 x i64> %l
|
|
}
|
|
|
|
define <2 x i64> @foo() {
|
|
; CHECK-LABEL: @foo(
|
|
; CHECK-NEXT: [[L:%.*]] = load <2 x i64>, ptr @x, align 1
|
|
; CHECK-NEXT: ret <2 x i64> [[L]]
|
|
;
|
|
%l = load <2 x i64>, ptr @x, align 1
|
|
ret <2 x i64> %l
|
|
}
|
|
|
|
define <2 x i64> @bar() {
|
|
; CHECK-LABEL: @bar(
|
|
; CHECK-NEXT: [[T:%.*]] = alloca <2 x i64>, align 16
|
|
; CHECK-NEXT: call void @kip(ptr nonnull [[T]])
|
|
; CHECK-NEXT: [[L:%.*]] = load <2 x i64>, ptr [[T]], align 1
|
|
; CHECK-NEXT: ret <2 x i64> [[L]]
|
|
;
|
|
%t = alloca <2 x i64>
|
|
call void @kip(ptr %t)
|
|
%l = load <2 x i64>, ptr %t, align 1
|
|
ret <2 x i64> %l
|
|
}
|
|
|
|
define void @static_hem_store(<2 x i64> %y) {
|
|
; CHECK-LABEL: @static_hem_store(
|
|
; CHECK-NEXT: store <2 x i64> [[Y:%.*]], ptr getelementptr (i8, ptr @x, i64 112), align 1
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%t = getelementptr <2 x i64>, ptr @x, i32 7
|
|
store <2 x i64> %y, ptr %t, align 1
|
|
ret void
|
|
}
|
|
|
|
define void @hem_store(i32 %i, <2 x i64> %y) {
|
|
; CHECK-LABEL: @hem_store(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I:%.*]] to i64
|
|
; CHECK-NEXT: [[T:%.*]] = getelementptr <2 x i64>, ptr @x, i64 [[TMP1]]
|
|
; CHECK-NEXT: store <2 x i64> [[Y:%.*]], ptr [[T]], align 1
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%t = getelementptr <2 x i64>, ptr @x, i32 %i
|
|
store <2 x i64> %y, ptr %t, align 1
|
|
ret void
|
|
}
|
|
|
|
define void @hem_2d_store(i32 %i, i32 %j, <2 x i64> %y) {
|
|
; CHECK-LABEL: @hem_2d_store(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I:%.*]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[J:%.*]] to i64
|
|
; CHECK-NEXT: [[T_SPLIT:%.*]] = getelementptr [13 x <2 x i64>], ptr @xx, i64 [[TMP1]]
|
|
; CHECK-NEXT: [[T:%.*]] = getelementptr <2 x i64>, ptr [[T_SPLIT]], i64 [[TMP2]]
|
|
; CHECK-NEXT: store <2 x i64> [[Y:%.*]], ptr [[T]], align 1
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%t = getelementptr [13 x <2 x i64>], ptr @xx, i32 %i, i32 %j
|
|
store <2 x i64> %y, ptr %t, align 1
|
|
ret void
|
|
}
|
|
|
|
define void @foo_store(<2 x i64> %y) {
|
|
; CHECK-LABEL: @foo_store(
|
|
; CHECK-NEXT: store <2 x i64> [[Y:%.*]], ptr @x, align 1
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
store <2 x i64> %y, ptr @x, align 1
|
|
ret void
|
|
}
|
|
|
|
define void @bar_store(<2 x i64> %y) {
|
|
; CHECK-LABEL: @bar_store(
|
|
; CHECK-NEXT: [[T:%.*]] = alloca <2 x i64>, align 16
|
|
; CHECK-NEXT: call void @kip(ptr nonnull [[T]])
|
|
; CHECK-NEXT: store <2 x i64> [[Y:%.*]], ptr [[T]], align 1
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%t = alloca <2 x i64>
|
|
call void @kip(ptr %t)
|
|
store <2 x i64> %y, ptr %t, align 1
|
|
ret void
|
|
}
|
|
|
|
declare void @kip(ptr %t)
|