1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4; This test is used to verify we are not crashing at Assertion `CastInst::castIsValid(opc, C, Ty) && "Invalid constantexpr cast!". 5define <vscale x 2 x ptr> @gep_index_type_is_scalable(ptr %p) { 6; CHECK-LABEL: @gep_index_type_is_scalable( 7; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P:%.*]], <vscale x 2 x i64> undef 8; CHECK-NEXT: ret <vscale x 2 x ptr> [[GEP]] 9; 10 %gep = getelementptr i8, ptr %p, <vscale x 2 x i64> undef 11 ret <vscale x 2 x ptr> %gep 12} 13 14; This test serves to verify code changes for "GEP.getNumIndices() == 1". 15define ptr @gep_num_of_indices_1(ptr %p) { 16; CHECK-LABEL: @gep_num_of_indices_1( 17; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 18; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 19; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[TMP2]] 20; CHECK-NEXT: ret ptr [[GEP]] 21; 22 %gep = getelementptr <vscale x 4 x i32>, ptr %p, i64 1 23 ret ptr %gep 24} 25 26; This test serves to verify code changes for "GEP.getNumOperands() == 2". 27define void @gep_bitcast(ptr %p) { 28; CHECK-LABEL: @gep_bitcast( 29; CHECK-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[P:%.*]], align 16 30; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 31; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 32; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP2]] 33; CHECK-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[GEP2]], align 16 34; CHECK-NEXT: ret void 35; 36 store <vscale x 16 x i8> zeroinitializer, ptr %p 37 %gep2 = getelementptr <vscale x 16 x i8>, ptr %p, i64 1 38 store <vscale x 16 x i8> zeroinitializer, ptr %gep2 39 ret void 40} 41 42; These tests serve to verify code changes when underlying gep ptr is alloca. 43; This test is to verify 'inbounds' is added when it's valid to accumulate constant offset. 44define i32 @gep_alloca_inbounds_vscale_zero() { 45; CHECK-LABEL: @gep_alloca_inbounds_vscale_zero( 46; CHECK-NEXT: [[A:%.*]] = alloca <vscale x 4 x i32>, align 16 47; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 8 48; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TMP]], align 4 49; CHECK-NEXT: ret i32 [[LOAD]] 50; 51 %a = alloca <vscale x 4 x i32> 52 %tmp = getelementptr <vscale x 4 x i32>, ptr %a, i32 0, i32 2 53 %load = load i32, ptr %tmp 54 ret i32 %load 55} 56 57; This test is to verify 'inbounds' is not added when a constant offset can not be determined at compile-time. 58define i32 @gep_alloca_inbounds_vscale_nonzero() { 59; CHECK-LABEL: @gep_alloca_inbounds_vscale_nonzero( 60; CHECK-NEXT: [[A:%.*]] = alloca <vscale x 4 x i32>, align 16 61; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 62; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 63; CHECK-NEXT: [[TMP_OFFS:%.*]] = or disjoint i64 [[TMP2]], 8 64; CHECK-NEXT: [[TMP:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP_OFFS]] 65; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TMP]], align 4 66; CHECK-NEXT: ret i32 [[LOAD]] 67; 68 %a = alloca <vscale x 4 x i32> 69 %tmp = getelementptr <vscale x 4 x i32>, ptr %a, i32 1, i32 2 70 %load = load i32, ptr %tmp 71 ret i32 %load 72} 73