488 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG3; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG4 5%st.half = type { half }6 7; Allow speculateSelectInstLoads to fold load and select8; even if there is an intervening bitcast.9define <2 x i16> @test_load_bitcast_select(i1 %cond1, i1 %cond2) {10; CHECK-LABEL: @test_load_bitcast_select(11; CHECK-NEXT: entry:12; CHECK-NEXT: [[TMP0:%.*]] = bitcast half 0xHFFFF to i1613; CHECK-NEXT: [[TMP1:%.*]] = bitcast half 0xH0000 to i1614; CHECK-NEXT: [[LD1_SROA_SPECULATED:%.*]] = select i1 [[COND1:%.*]], i16 [[TMP0]], i16 [[TMP1]]15; CHECK-NEXT: [[V1:%.*]] = insertelement <2 x i16> poison, i16 [[LD1_SROA_SPECULATED]], i32 016; CHECK-NEXT: [[TMP2:%.*]] = bitcast half 0xHFFFF to i1617; CHECK-NEXT: [[TMP3:%.*]] = bitcast half 0xH0000 to i1618; CHECK-NEXT: [[LD2_SROA_SPECULATED:%.*]] = select i1 [[COND2:%.*]], i16 [[TMP2]], i16 [[TMP3]]19; CHECK-NEXT: [[V2:%.*]] = insertelement <2 x i16> [[V1]], i16 [[LD2_SROA_SPECULATED]], i32 120; CHECK-NEXT: ret <2 x i16> [[V2]]21;22entry:23 %true = alloca half, align 224 %false = alloca half, align 225 store half 0xHFFFF, ptr %true, align 226 store half 0xH0000, ptr %false, align 227 %sel1 = select i1 %cond1, ptr %true, ptr %false28 %ld1 = load i16, ptr %sel1, align 229 %v1 = insertelement <2 x i16> poison, i16 %ld1, i32 030 %sel2 = select i1 %cond2, ptr %true, ptr %false31 %ld2 = load i16, ptr %sel2, align 232 %v2 = insertelement <2 x i16> %v1, i16 %ld2, i32 133 ret <2 x i16> %v234}35 36%st.args = type { i32, ptr }37 38; A bitcasted load and a direct load of select.39define void @test_multiple_loads_select(i1 %cmp) {40; CHECK-LABEL: @test_multiple_loads_select(41; CHECK-NEXT: entry:42; CHECK-NEXT: [[ADDR_I8_SROA_SPECULATED:%.*]] = select i1 [[CMP:%.*]], ptr undef, ptr undef43; CHECK-NEXT: call void @foo_i8(ptr [[ADDR_I8_SROA_SPECULATED]])44; CHECK-NEXT: [[ADDR_I32_SROA_SPECULATED:%.*]] = select i1 [[CMP]], ptr undef, ptr undef45; CHECK-NEXT: call void @foo_i32(ptr [[ADDR_I32_SROA_SPECULATED]])46; CHECK-NEXT: ret void47;48entry:49 %args = alloca [2 x %st.args], align 1650 %arr1 = getelementptr inbounds [2 x %st.args], ptr %args, i64 0, i64 151 %sel = select i1 %cmp, ptr %arr1, ptr %args52 %addr = getelementptr inbounds %st.args, ptr %sel, i64 0, i32 153 %addr.i8 = load ptr, ptr %addr, align 854 call void @foo_i8(ptr %addr.i8)55 %addr.i32 = load ptr, ptr %addr, align 856 call void @foo_i32 (ptr %addr.i32)57 ret void58}59 60; Sanitizer will break optimization.61define void @test_multiple_loads_select_asan(i1 %cmp) sanitize_address {62; CHECK-PRESERVE-CFG-LABEL: @test_multiple_loads_select_asan(63; CHECK-PRESERVE-CFG-NEXT: entry:64; CHECK-PRESERVE-CFG-NEXT: [[ARGS_SROA_0:%.*]] = alloca ptr, align 865; CHECK-PRESERVE-CFG-NEXT: [[ARGS_SROA_1:%.*]] = alloca ptr, align 866; CHECK-PRESERVE-CFG-NEXT: [[SEL_SROA_SEL:%.*]] = select i1 [[CMP:%.*]], ptr [[ARGS_SROA_1]], ptr [[ARGS_SROA_0]]67; CHECK-PRESERVE-CFG-NEXT: [[ADDR_I8:%.*]] = load ptr, ptr [[SEL_SROA_SEL]], align 868; CHECK-PRESERVE-CFG-NEXT: call void @foo_i8(ptr [[ADDR_I8]])69; CHECK-PRESERVE-CFG-NEXT: [[ADDR_I32:%.*]] = load ptr, ptr [[SEL_SROA_SEL]], align 870; CHECK-PRESERVE-CFG-NEXT: call void @foo_i32(ptr [[ADDR_I32]])71; CHECK-PRESERVE-CFG-NEXT: ret void72;73; CHECK-MODIFY-CFG-LABEL: @test_multiple_loads_select_asan(74; CHECK-MODIFY-CFG-NEXT: entry:75; CHECK-MODIFY-CFG-NEXT: br i1 [[CMP:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]]76; CHECK-MODIFY-CFG: entry.then:77; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT:%.*]]78; CHECK-MODIFY-CFG: entry.else:79; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]80; CHECK-MODIFY-CFG: entry.cont:81; CHECK-MODIFY-CFG-NEXT: [[ADDR_I8:%.*]] = phi ptr [ undef, [[ENTRY_THEN]] ], [ undef, [[ENTRY_ELSE]] ]82; CHECK-MODIFY-CFG-NEXT: call void @foo_i8(ptr [[ADDR_I8]])83; CHECK-MODIFY-CFG-NEXT: br i1 [[CMP]], label [[ENTRY_CONT_THEN:%.*]], label [[ENTRY_CONT_ELSE:%.*]]84; CHECK-MODIFY-CFG: entry.cont.then:85; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT_CONT:%.*]]86; CHECK-MODIFY-CFG: entry.cont.else:87; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT_CONT]]88; CHECK-MODIFY-CFG: entry.cont.cont:89; CHECK-MODIFY-CFG-NEXT: [[ADDR_I32:%.*]] = phi ptr [ undef, [[ENTRY_CONT_THEN]] ], [ undef, [[ENTRY_CONT_ELSE]] ]90; CHECK-MODIFY-CFG-NEXT: call void @foo_i32(ptr [[ADDR_I32]])91; CHECK-MODIFY-CFG-NEXT: ret void92;93entry:94 %args = alloca [2 x %st.args], align 1695 %arr1 = getelementptr inbounds [2 x %st.args], ptr %args, i64 0, i64 196 %sel = select i1 %cmp, ptr %arr1, ptr %args97 %addr = getelementptr inbounds %st.args, ptr %sel, i64 0, i32 198 %addr.i8 = load ptr, ptr %addr, align 899 call void @foo_i8(ptr %addr.i8)100 %addr.i32 = load ptr, ptr %addr, align 8101 call void @foo_i32 (ptr %addr.i32)102 ret void103}104 105declare void @foo_i8(ptr)106declare void @foo_i32(ptr)107 108; Lifetime intrinsics should not prevent dereferenceability inferrence.109define i32 @interfering_lifetime(ptr %data, i64 %indvars.iv) {110; CHECK-LABEL: @interfering_lifetime(111; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]112; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4113; CHECK-NEXT: [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0114; CHECK-NEXT: [[I3_SROA_SPECULATE_LOAD_FALSE:%.*]] = load i32, ptr [[ARRAYIDX]], align 4115; CHECK-NEXT: [[I3_SROA_SPECULATED:%.*]] = select i1 [[CMP_I_I]], i32 0, i32 [[I3_SROA_SPECULATE_LOAD_FALSE]]116; CHECK-NEXT: ret i32 [[I3_SROA_SPECULATED]]117;118 %min = alloca i32, align 4119 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv120 %i1 = load i32, ptr %arrayidx, align 4121 call void @llvm.lifetime.start.p0(ptr %min)122 store i32 0, ptr %min, align 4123 %cmp.i.i = icmp slt i32 %i1, 0124 %__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx125 %i3 = load i32, ptr %__b.__a.i.i, align 4126 ret i32 %i3127}128 129; We should recursively evaluate select's.130define i32 @clamp_load_to_constant_range(ptr %data, i64 %indvars.iv) {131; CHECK-PRESERVE-CFG-LABEL: @clamp_load_to_constant_range(132; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4133; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4134; CHECK-PRESERVE-CFG-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]135; CHECK-PRESERVE-CFG-NEXT: call void @llvm.lifetime.start.p0(ptr [[MIN]])136; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4137; CHECK-PRESERVE-CFG-NEXT: call void @llvm.lifetime.start.p0(ptr [[MAX]])138; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4139; CHECK-PRESERVE-CFG-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4140; CHECK-PRESERVE-CFG-NEXT: [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0141; CHECK-PRESERVE-CFG-NEXT: [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)142; CHECK-PRESERVE-CFG-NEXT: [[__B___A_I_I:%.*]] = select i1 [[CMP_I_I]], ptr [[MIN]], ptr [[ARRAYIDX]]143; CHECK-PRESERVE-CFG-NEXT: [[CMP_I1_I:%.*]] = icmp ugt i32 [[I2]], 4095144; CHECK-PRESERVE-CFG-NEXT: [[__B___A_I2_I:%.*]] = select i1 [[CMP_I1_I]], ptr [[MAX]], ptr [[__B___A_I_I]]145; CHECK-PRESERVE-CFG-NEXT: [[I3:%.*]] = load i32, ptr [[__B___A_I2_I]], align 4146; CHECK-PRESERVE-CFG-NEXT: ret i32 [[I3]]147;148; CHECK-MODIFY-CFG-LABEL: @clamp_load_to_constant_range(149; CHECK-MODIFY-CFG-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]150; CHECK-MODIFY-CFG-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4151; CHECK-MODIFY-CFG-NEXT: [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0152; CHECK-MODIFY-CFG-NEXT: [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)153; CHECK-MODIFY-CFG-NEXT: [[CMP_I1_I:%.*]] = icmp ugt i32 [[I2]], 4095154; CHECK-MODIFY-CFG-NEXT: br i1 [[CMP_I1_I]], label [[DOTCONT:%.*]], label [[DOTELSE:%.*]]155; CHECK-MODIFY-CFG: .else:156; CHECK-MODIFY-CFG-NEXT: br i1 [[CMP_I_I]], label [[DOTELSE_CONT:%.*]], label [[DOTELSE_ELSE:%.*]]157; CHECK-MODIFY-CFG: .else.else:158; CHECK-MODIFY-CFG-NEXT: [[I3_ELSE_VAL_ELSE_VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4159; CHECK-MODIFY-CFG-NEXT: br label [[DOTELSE_CONT]]160; CHECK-MODIFY-CFG: .else.cont:161; CHECK-MODIFY-CFG-NEXT: [[I3_ELSE_VAL:%.*]] = phi i32 [ 0, [[DOTELSE]] ], [ [[I3_ELSE_VAL_ELSE_VAL]], [[DOTELSE_ELSE]] ]162; CHECK-MODIFY-CFG-NEXT: br label [[DOTCONT]]163; CHECK-MODIFY-CFG: .cont:164; CHECK-MODIFY-CFG-NEXT: [[I3:%.*]] = phi i32 [ 4095, [[TMP0:%.*]] ], [ [[I3_ELSE_VAL]], [[DOTELSE_CONT]] ]165; CHECK-MODIFY-CFG-NEXT: ret i32 [[I3]]166;167 %min = alloca i32, align 4168 %max = alloca i32, align 4169 %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv170 call void @llvm.lifetime.start.p0(ptr %min)171 store i32 0, ptr %min, align 4172 call void @llvm.lifetime.start.p0(ptr %max)173 store i32 4095, ptr %max, align 4174 %i1 = load i32, ptr %arrayidx, align 4175 %cmp.i.i = icmp slt i32 %i1, 0176 %i2 = tail call i32 @llvm.smax.i32(i32 %i1, i32 0)177 %__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx178 %cmp.i1.i = icmp ugt i32 %i2, 4095179 %__b.__a.i2.i = select i1 %cmp.i1.i, ptr %max, ptr %__b.__a.i.i180 %i3 = load i32, ptr %__b.__a.i2.i, align 4181 ret i32 %i3182}183 184define i32 @non_speculatable_load_of_select(i1 %cond, ptr %else.addr) {185; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select(186; CHECK-PRESERVE-CFG-NEXT: entry:187; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4188; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4189; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0:![0-9]+]]190; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4191; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]192;193; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select(194; CHECK-MODIFY-CFG-NEXT: entry:195; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_CONT:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF0:![0-9]+]]196; CHECK-MODIFY-CFG: entry.else:197; CHECK-MODIFY-CFG-NEXT: [[R_ELSE_VAL:%.*]] = load i32, ptr [[ELSE_ADDR:%.*]], align 4198; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]199; CHECK-MODIFY-CFG: entry.cont:200; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]201; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]202;203entry:204 %min = alloca i32, align 4205 store i32 0, ptr %min, align 4206 %addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0207 %r = load i32, ptr %addr, align 4208 ret i32 %r209}210define i32 @non_speculatable_load_of_select_inverted(i1 %cond, ptr %then.addr) {211; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inverted(212; CHECK-PRESERVE-CFG-NEXT: entry:213; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4214; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4215; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]216; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4217; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]218;219; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inverted(220; CHECK-MODIFY-CFG-NEXT: entry:221; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_CONT:%.*]], !prof [[PROF1:![0-9]+]]222; CHECK-MODIFY-CFG: entry.then:223; CHECK-MODIFY-CFG-NEXT: [[R_THEN_VAL:%.*]] = load i32, ptr [[THEN_ADDR:%.*]], align 4224; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]225; CHECK-MODIFY-CFG: entry.cont:226; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 4095, [[ENTRY:%.*]] ]227; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]228;229entry:230 %max = alloca i32, align 4231 store i32 4095, ptr %max, align 4232 %addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0233 %r = load i32, ptr %addr, align 4234 ret i32 %r235}236 237define i32 @non_speculatable_volatile_load_of_select(i1 %cond, ptr %else.addr) {238; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_volatile_load_of_select(239; CHECK-PRESERVE-CFG-NEXT: entry:240; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4241; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4242; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0]]243; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4244; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]245;246; CHECK-MODIFY-CFG-LABEL: @non_speculatable_volatile_load_of_select(247; CHECK-MODIFY-CFG-NEXT: entry:248; CHECK-MODIFY-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4249; CHECK-MODIFY-CFG-NEXT: store i32 0, ptr [[MIN]], align 4250; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF1]]251; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4252; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]253;254entry:255 %min = alloca i32, align 4256 store i32 0, ptr %min, align 4257 %addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0258 %r = load volatile i32, ptr %addr, align 4259 ret i32 %r260}261define i32 @non_speculatable_volatile_load_of_select_inverted(i1 %cond, ptr %then.addr) {262; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_volatile_load_of_select_inverted(263; CHECK-PRESERVE-CFG-NEXT: entry:264; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4265; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4266; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]267; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4268; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]269;270; CHECK-MODIFY-CFG-LABEL: @non_speculatable_volatile_load_of_select_inverted(271; CHECK-MODIFY-CFG-NEXT: entry:272; CHECK-MODIFY-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4273; CHECK-MODIFY-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4274; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF1]]275; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4276; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]277;278entry:279 %max = alloca i32, align 4280 store i32 4095, ptr %max, align 4281 %addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0282 %r = load volatile i32, ptr %addr, align 4283 ret i32 %r284}285 286define i32 @non_speculatable_atomic_unord_load_of_select(i1 %cond, ptr %else.addr) {287; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select(288; CHECK-PRESERVE-CFG-NEXT: entry:289; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4290; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4291; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0]]292; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4293; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]294;295; CHECK-MODIFY-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select(296; CHECK-MODIFY-CFG-NEXT: entry:297; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF1]]298; CHECK-MODIFY-CFG: entry.then:299; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT:%.*]]300; CHECK-MODIFY-CFG: entry.else:301; CHECK-MODIFY-CFG-NEXT: [[R_ELSE_VAL:%.*]] = load atomic i32, ptr [[ELSE_ADDR:%.*]] unordered, align 4302; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]303; CHECK-MODIFY-CFG: entry.cont:304; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY_THEN]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]305; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]306;307entry:308 %min = alloca i32, align 4309 store i32 0, ptr %min, align 4310 %addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0311 %r = load atomic i32, ptr %addr unordered, align 4312 ret i32 %r313}314define i32 @non_speculatable_atomic_unord_load_of_select_inverted(i1 %cond, ptr %then.addr) {315; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select_inverted(316; CHECK-PRESERVE-CFG-NEXT: entry:317; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4318; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4319; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]320; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4321; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]322;323; CHECK-MODIFY-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select_inverted(324; CHECK-MODIFY-CFG-NEXT: entry:325; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF1]]326; CHECK-MODIFY-CFG: entry.then:327; CHECK-MODIFY-CFG-NEXT: [[R_THEN_VAL:%.*]] = load atomic i32, ptr [[THEN_ADDR:%.*]] unordered, align 4328; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT:%.*]]329; CHECK-MODIFY-CFG: entry.else:330; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]331; CHECK-MODIFY-CFG: entry.cont:332; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 4095, [[ENTRY_ELSE]] ]333; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]334;335entry:336 %max = alloca i32, align 4337 store i32 4095, ptr %max, align 4338 %addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0339 %r = load atomic i32, ptr %addr unordered, align 4340 ret i32 %r341}342 343define i32 @non_speculatable_load_of_select_outer(i1 %cond_inner, i1 %cond_outer, ptr %data_then, ptr %data_else) {344; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_outer(345; CHECK-PRESERVE-CFG-NEXT: entry:346; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4347; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4348; CHECK-PRESERVE-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]349; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN]], ptr [[ADDR_DATA]], !prof [[PROF0]]350; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4351; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]352;353; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_outer(354; CHECK-MODIFY-CFG-NEXT: entry:355; CHECK-MODIFY-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]356; CHECK-MODIFY-CFG-NEXT: br i1 [[COND_OUTER:%.*]], label [[ENTRY_CONT:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF0]]357; CHECK-MODIFY-CFG: entry.else:358; CHECK-MODIFY-CFG-NEXT: [[R_ELSE_VAL:%.*]] = load i32, ptr [[ADDR_DATA]], align 4359; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]360; CHECK-MODIFY-CFG: entry.cont:361; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]362; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]363;364entry:365 %min = alloca i32, align 4366 store i32 0, ptr %min, align 4367 %addr.data = select i1 %cond_inner, ptr %data_then, ptr %data_else, !prof !0368 %addr = select i1 %cond_outer, ptr %min, ptr %addr.data, !prof !0369 %r = load i32, ptr %addr, align 4370 ret i32 %r371}372define i32 @non_speculatable_load_of_select_outer_inverted(i1 %cond_inner, i1 %cond_outer, ptr %data_then, ptr %data_else) {373; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_outer_inverted(374; CHECK-PRESERVE-CFG-NEXT: entry:375; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4376; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4377; CHECK-PRESERVE-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]378; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[ADDR_DATA]], ptr [[MIN]], !prof [[PROF0]]379; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4380; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]381;382; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_outer_inverted(383; CHECK-MODIFY-CFG-NEXT: entry:384; CHECK-MODIFY-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]385; CHECK-MODIFY-CFG-NEXT: br i1 [[COND_OUTER:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_CONT:%.*]], !prof [[PROF1]]386; CHECK-MODIFY-CFG: entry.then:387; CHECK-MODIFY-CFG-NEXT: [[R_THEN_VAL:%.*]] = load i32, ptr [[ADDR_DATA]], align 4388; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]389; CHECK-MODIFY-CFG: entry.cont:390; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 0, [[ENTRY:%.*]] ]391; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]392;393entry:394 %min = alloca i32, align 4395 store i32 0, ptr %min, align 4396 %addr.data = select i1 %cond_inner, ptr %data_then, ptr %data_else, !prof !0397 %addr = select i1 %cond_outer, ptr %addr.data, ptr %min, !prof !0398 %r = load i32, ptr %addr, align 4399 ret i32 %r400}401 402define i32 @non_speculatable_load_of_select_inner(i1 %cond_inner, i1 %cond_outer, ptr %data_else, ptr %min_else) {403; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inner(404; CHECK-PRESERVE-CFG-NEXT: entry:405; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4406; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4407; CHECK-PRESERVE-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN]], ptr [[MIN_ELSE:%.*]], !prof [[PROF0]]408; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]409; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4410; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]411;412; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inner(413; CHECK-MODIFY-CFG-NEXT: entry:414; CHECK-MODIFY-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4415; CHECK-MODIFY-CFG-NEXT: store i32 0, ptr [[MIN]], align 4416; CHECK-MODIFY-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN]], ptr [[MIN_ELSE:%.*]], !prof [[PROF1]]417; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]418; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4419; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]420;421entry:422 %min = alloca i32, align 4423 store i32 0, ptr %min, align 4424 %min.addr.data = select i1 %cond_inner, ptr %min, ptr %min_else, !prof !0425 %addr = select i1 %cond_outer, ptr %min.addr.data, ptr %data_else, !prof !0426 %r = load i32, ptr %addr, align 4427 ret i32 %r428}429define i32 @non_speculatable_load_of_select_inner_inverted(i1 %cond_inner, i1 %cond_outer, ptr %data_else, ptr %min_then) {430; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inner_inverted(431; CHECK-PRESERVE-CFG-NEXT: entry:432; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4433; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4434; CHECK-PRESERVE-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN_THEN:%.*]], ptr [[MIN]], !prof [[PROF0]]435; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]436; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4437; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]438;439; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inner_inverted(440; CHECK-MODIFY-CFG-NEXT: entry:441; CHECK-MODIFY-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4442; CHECK-MODIFY-CFG-NEXT: store i32 0, ptr [[MIN]], align 4443; CHECK-MODIFY-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN_THEN:%.*]], ptr [[MIN]], !prof [[PROF1]]444; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]445; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4446; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]447;448entry:449 %min = alloca i32, align 4450 store i32 0, ptr %min, align 4451 %min.addr.data = select i1 %cond_inner, ptr %min_then, ptr %min, !prof !0452 %addr = select i1 %cond_outer, ptr %min.addr.data, ptr %data_else, !prof !0453 %r = load i32, ptr %addr, align 4454 ret i32 %r455}456 457; When promoting speculative instruction, metadata that may trigger immediate UB should be dropped.458define void @load_of_select_with_noundef_nonnull(ptr %buffer, i1 %b) {459; CHECK-PRESERVE-CFG-LABEL: @load_of_select_with_noundef_nonnull(460; CHECK-PRESERVE-CFG-NEXT: [[UB_PTR:%.*]] = alloca ptr, align 8461; CHECK-PRESERVE-CFG-NEXT: [[SELECT_PTR:%.*]] = select i1 [[B:%.*]], ptr [[BUFFER:%.*]], ptr [[UB_PTR]]462; CHECK-PRESERVE-CFG-NEXT: [[LOAD_PTR:%.*]] = load ptr, ptr [[SELECT_PTR]], align 8, !nonnull [[META1:![0-9]+]], !noundef [[META1]]463; CHECK-PRESERVE-CFG-NEXT: ret void464;465; CHECK-MODIFY-CFG-LABEL: @load_of_select_with_noundef_nonnull(466; CHECK-MODIFY-CFG-NEXT: br i1 [[B:%.*]], label [[DOTTHEN:%.*]], label [[DOTCONT:%.*]]467; CHECK-MODIFY-CFG: .then:468; CHECK-MODIFY-CFG-NEXT: [[LOAD_PTR_THEN_VAL:%.*]] = load ptr, ptr [[BUFFER:%.*]], align 8, !nonnull [[META2:![0-9]+]], !noundef [[META2]]469; CHECK-MODIFY-CFG-NEXT: br label [[DOTCONT]]470; CHECK-MODIFY-CFG: .cont:471; CHECK-MODIFY-CFG-NEXT: [[LOAD_PTR:%.*]] = phi ptr [ [[LOAD_PTR_THEN_VAL]], [[DOTTHEN]] ], [ undef, [[TMP0:%.*]] ]472; CHECK-MODIFY-CFG-NEXT: ret void473;474 %ub_ptr = alloca ptr475 %select_ptr = select i1 %b, ptr %buffer, ptr %ub_ptr476 %load_ptr = load ptr, ptr %select_ptr, !nonnull !1, !noundef !1477 ret void478}479 480!0 = !{!"branch_weights", i32 1, i32 99}481!1 = !{}482 483; Ensure that the branch metadata is reversed to match the reversals above.484 485declare void @llvm.lifetime.start.p0(ptr )486declare void @llvm.lifetime.end.p0(ptr)487declare i32 @llvm.smax.i32(i32, i32)488