950 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=separate-const-offset-from-gep < %s | FileCheck %s3 4declare void @use.i32(i32 noundef)5declare void @allow.undef.use.i32(i32)6 7declare void @use.v2i32(<2 x i32> noundef)8declare void @allow.undef.use.v2i32(<2 x i32>)9 10declare void @use.i64(i64 noundef)11 12; Should fold out the 64-bit add13define i64 @add_sext__dominating_add_nsw(i32 %arg0, i32 %arg1) {14; CHECK-LABEL: define i64 @add_sext__dominating_add_nsw15; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0:[0-9]+]] {16; CHECK-NEXT: entry:17; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]18; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext i32 [[ADD_NSW]] to i6419; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])20; CHECK-NEXT: ret i64 [[ADD_SEXT]]21;22entry:23 %add.nsw = add nsw i32 %arg0, %arg124 %arg0.sext = sext i32 %arg0 to i6425 %arg1.sext = sext i32 %arg1 to i6426 %add.sext = add i64 %arg0.sext, %arg1.sext27 call void @use.i32(i32 %add.nsw)28 ret i64 %add.sext29}30 31; Should fold out the 64-bit sub32define i64 @sub_sext__dominating_sub_nsw(i32 %arg0, i32 %arg1) {33; CHECK-LABEL: define i64 @sub_sext__dominating_sub_nsw34; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {35; CHECK-NEXT: entry:36; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]37; CHECK-NEXT: [[SUB_SEXT:%.*]] = sext i32 [[SUB_NSW]] to i6438; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])39; CHECK-NEXT: ret i64 [[SUB_SEXT]]40;41entry:42 %sub.nsw = sub nsw i32 %arg0, %arg143 %arg0.sext = sext i32 %arg0 to i6444 %arg1.sext = sext i32 %arg1 to i6445 %sub.sext = sub i64 %arg0.sext, %arg1.sext46 call void @use.i32(i32 %sub.nsw)47 ret i64 %sub.sext48}49 50; Should fold out the 64-bit add. The 64-bit add has commuted operands51; compared to the original.52define i64 @add_sext__dominating_add_nsw_commuted(i32 %arg0, i32 %arg1) {53; CHECK-LABEL: define i64 @add_sext__dominating_add_nsw_commuted54; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {55; CHECK-NEXT: entry:56; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]57; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext i32 [[ADD_NSW]] to i6458; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])59; CHECK-NEXT: ret i64 [[ADD_SEXT]]60;61entry:62 %add.nsw = add nsw i32 %arg0, %arg163 %arg0.sext = sext i32 %arg0 to i6464 %arg1.sext = sext i32 %arg1 to i6465 %add.sext = add i64 %arg1.sext, %arg0.sext66 call void @use.i32(i32 %add.nsw)67 ret i64 %add.sext68}69 70; The second sub has commuted operands71define i64 @sub_sext__dominating_sub_nsw_commuted(i32 %arg0, i32 %arg1) {72; CHECK-LABEL: define i64 @sub_sext__dominating_sub_nsw_commuted73; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {74; CHECK-NEXT: entry:75; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]76; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i6477; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i6478; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG1_SEXT]], [[ARG0_SEXT]]79; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])80; CHECK-NEXT: ret i64 [[SUB_SEXT]]81;82entry:83 %sub.nsw = sub nsw i32 %arg0, %arg184 %arg0.sext = sext i32 %arg0 to i6485 %arg1.sext = sext i32 %arg1 to i6486 %sub.sext = sub i64 %arg1.sext, %arg0.sext87 call void @use.i32(i32 %sub.nsw)88 ret i64 %sub.sext89}90 91; Missing nsw on the add i32, can't do anything92define i64 @add_sext__dominating_add(i32 %arg0, i32 %arg1) {93; CHECK-LABEL: define i64 @add_sext__dominating_add94; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {95; CHECK-NEXT: entry:96; CHECK-NEXT: [[ADD_NSW:%.*]] = add i32 [[ARG0]], [[ARG1]]97; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i6498; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i6499; CHECK-NEXT: [[ADD_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]100; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])101; CHECK-NEXT: ret i64 [[ADD_SEXT]]102;103entry:104 %add.nsw = add i32 %arg0, %arg1105 %arg0.sext = sext i32 %arg0 to i64106 %arg1.sext = sext i32 %arg1 to i64107 %add.sext = add i64 %arg0.sext, %arg1.sext108 call void @use.i32(i32 %add.nsw)109 ret i64 %add.sext110}111 112; Missing nsw on the sub i32, can't do anything113define i64 @sub_sext__dominating_sub(i32 %arg0, i32 %arg1) {114; CHECK-LABEL: define i64 @sub_sext__dominating_sub115; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {116; CHECK-NEXT: entry:117; CHECK-NEXT: [[SUB_NSW:%.*]] = sub i32 [[ARG0]], [[ARG1]]118; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64119; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64120; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]121; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])122; CHECK-NEXT: ret i64 [[SUB_SEXT]]123;124entry:125 %sub.nsw = sub i32 %arg0, %arg1126 %arg0.sext = sext i32 %arg0 to i64127 %arg1.sext = sext i32 %arg1 to i64128 %sub.sext = sub i64 %arg0.sext, %arg1.sext129 call void @use.i32(i32 %sub.nsw)130 ret i64 %sub.sext131}132 133; The use of the 32-bit add allows poison, so can't fold.134define i64 @add_sext__dominating_add_nsw_defined(i32 %arg0, i32 %arg1) {135; CHECK-LABEL: define i64 @add_sext__dominating_add_nsw_defined136; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {137; CHECK-NEXT: entry:138; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]139; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64140; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64141; CHECK-NEXT: [[ADD_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]142; CHECK-NEXT: call void @allow.undef.use.i32(i32 [[ADD_NSW]])143; CHECK-NEXT: ret i64 [[ADD_SEXT]]144;145entry:146 %add.nsw = add nsw i32 %arg0, %arg1147 %arg0.sext = sext i32 %arg0 to i64148 %arg1.sext = sext i32 %arg1 to i64149 %add.sext = add i64 %arg0.sext, %arg1.sext150 call void @allow.undef.use.i32(i32 %add.nsw)151 ret i64 %add.sext152}153 154; The use of the 32-bit sub allows poison, so can't fold.155define i64 @sub_sext__dominating_sub_nsw_defined(i32 %arg0, i32 %arg1) {156; CHECK-LABEL: define i64 @sub_sext__dominating_sub_nsw_defined157; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {158; CHECK-NEXT: entry:159; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]160; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64161; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64162; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]163; CHECK-NEXT: call void @allow.undef.use.i32(i32 [[SUB_NSW]])164; CHECK-NEXT: ret i64 [[SUB_SEXT]]165;166entry:167 %sub.nsw = sub nsw i32 %arg0, %arg1168 %arg0.sext = sext i32 %arg0 to i64169 %arg1.sext = sext i32 %arg1 to i64170 %sub.sext = sub i64 %arg0.sext, %arg1.sext171 call void @allow.undef.use.i32(i32 %sub.nsw)172 ret i64 %sub.sext173}174 175define i64 @add_sext__dominating_add_nsw_multi_use_sext0(i32 %arg0, i32 %arg1) {176; CHECK-LABEL: define i64 @add_sext__dominating_add_nsw_multi_use_sext0177; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {178; CHECK-NEXT: entry:179; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]180; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64181; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64182; CHECK-NEXT: [[ADD_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]183; CHECK-NEXT: call void @use.i64(i64 [[ARG0_SEXT]])184; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])185; CHECK-NEXT: ret i64 [[ADD_SEXT]]186;187entry:188 %add.nsw = add nsw i32 %arg0, %arg1189 %arg0.sext = sext i32 %arg0 to i64190 %arg1.sext = sext i32 %arg1 to i64191 %add.sext = add i64 %arg0.sext, %arg1.sext192 call void @use.i64(i64 %arg0.sext)193 call void @use.i32(i32 %add.nsw)194 ret i64 %add.sext195}196 197define i64 @add_sext__dominating_add_nsw_multi_use_sext1(i32 %arg0, i32 %arg1) {198; CHECK-LABEL: define i64 @add_sext__dominating_add_nsw_multi_use_sext1199; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {200; CHECK-NEXT: entry:201; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]202; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64203; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64204; CHECK-NEXT: [[ADD_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]205; CHECK-NEXT: call void @use.i64(i64 [[ARG1_SEXT]])206; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])207; CHECK-NEXT: ret i64 [[ADD_SEXT]]208;209entry:210 %add.nsw = add nsw i32 %arg0, %arg1211 %arg0.sext = sext i32 %arg0 to i64212 %arg1.sext = sext i32 %arg1 to i64213 %add.sext = add i64 %arg0.sext, %arg1.sext214 call void @use.i64(i64 %arg1.sext)215 call void @use.i32(i32 %add.nsw)216 ret i64 %add.sext217}218 219define i64 @sub_sext__dominating_sub_nsw_multi_use_sext0(i32 %arg0, i32 %arg1) {220; CHECK-LABEL: define i64 @sub_sext__dominating_sub_nsw_multi_use_sext0221; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {222; CHECK-NEXT: entry:223; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]224; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64225; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64226; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]227; CHECK-NEXT: call void @use.i64(i64 [[ARG0_SEXT]])228; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])229; CHECK-NEXT: ret i64 [[SUB_SEXT]]230;231entry:232 %sub.nsw = sub nsw i32 %arg0, %arg1233 %arg0.sext = sext i32 %arg0 to i64234 %arg1.sext = sext i32 %arg1 to i64235 %sub.sext = sub i64 %arg0.sext, %arg1.sext236 call void @use.i64(i64 %arg0.sext)237 call void @use.i32(i32 %sub.nsw)238 ret i64 %sub.sext239}240 241define i64 @sub_sext__dominating_sub_nsw_multi_use_sext1(i32 %arg0, i32 %arg1) {242; CHECK-LABEL: define i64 @sub_sext__dominating_sub_nsw_multi_use_sext1243; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {244; CHECK-NEXT: entry:245; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]246; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64247; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64248; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]249; CHECK-NEXT: call void @use.i64(i64 [[ARG1_SEXT]])250; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])251; CHECK-NEXT: ret i64 [[SUB_SEXT]]252;253entry:254 %sub.nsw = sub nsw i32 %arg0, %arg1255 %arg0.sext = sext i32 %arg0 to i64256 %arg1.sext = sext i32 %arg1 to i64257 %sub.sext = sub i64 %arg0.sext, %arg1.sext258 call void @use.i64(i64 %arg1.sext)259 call void @use.i32(i32 %sub.nsw)260 ret i64 %sub.sext261}262 263; --------------------------------------------------------------------264; Vector handling265; --------------------------------------------------------------------266 267; Should fold out the 64-bit add268define <2 x i64> @add_sext__dominating_add_nsw_vector(<2 x i32> %arg0, <2 x i32> %arg1) {269; CHECK-LABEL: define <2 x i64> @add_sext__dominating_add_nsw_vector270; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {271; CHECK-NEXT: entry:272; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw <2 x i32> [[ARG0]], [[ARG1]]273; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext <2 x i32> [[ADD_NSW]] to <2 x i64>274; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[ADD_NSW]])275; CHECK-NEXT: ret <2 x i64> [[ADD_SEXT]]276;277entry:278 %add.nsw = add nsw <2 x i32> %arg0, %arg1279 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>280 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>281 %add.sext = add <2 x i64> %arg0.sext, %arg1.sext282 call void @use.v2i32(<2 x i32> %add.nsw)283 ret <2 x i64> %add.sext284}285 286; Should fold out the 64-bit sub287define <2 x i64> @sub_sext__dominating_sub_nsw_vector(<2 x i32> %arg0, <2 x i32> %arg1) {288; CHECK-LABEL: define <2 x i64> @sub_sext__dominating_sub_nsw_vector289; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {290; CHECK-NEXT: entry:291; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw <2 x i32> [[ARG0]], [[ARG1]]292; CHECK-NEXT: [[SUB_SEXT:%.*]] = sext <2 x i32> [[SUB_NSW]] to <2 x i64>293; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[SUB_NSW]])294; CHECK-NEXT: ret <2 x i64> [[SUB_SEXT]]295;296entry:297 %sub.nsw = sub nsw <2 x i32> %arg0, %arg1298 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>299 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>300 %sub.sext = sub <2 x i64> %arg0.sext, %arg1.sext301 call void @use.v2i32(<2 x i32> %sub.nsw)302 ret <2 x i64> %sub.sext303}304 305; Should fold out the 64-bit add. The 64-bit add has commuted operands306; compared to the original.307define <2 x i64> @add_sext__dominating_add_nsw_commuted_vector(<2 x i32> %arg0, <2 x i32> %arg1) {308; CHECK-LABEL: define <2 x i64> @add_sext__dominating_add_nsw_commuted_vector309; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {310; CHECK-NEXT: entry:311; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw <2 x i32> [[ARG0]], [[ARG1]]312; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext <2 x i32> [[ADD_NSW]] to <2 x i64>313; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[ADD_NSW]])314; CHECK-NEXT: ret <2 x i64> [[ADD_SEXT]]315;316entry:317 %add.nsw = add nsw <2 x i32> %arg0, %arg1318 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>319 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>320 %add.sext = add <2 x i64> %arg1.sext, %arg0.sext321 call void @use.v2i32(<2 x i32> %add.nsw)322 ret <2 x i64> %add.sext323}324 325; The second sub has commuted operands326define <2 x i64> @sub_sext__dominating_sub_nsw_commuted_vector(<2 x i32> %arg0, <2 x i32> %arg1) {327; CHECK-LABEL: define <2 x i64> @sub_sext__dominating_sub_nsw_commuted_vector328; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {329; CHECK-NEXT: entry:330; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw <2 x i32> [[ARG0]], [[ARG1]]331; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext <2 x i32> [[ARG0]] to <2 x i64>332; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext <2 x i32> [[ARG1]] to <2 x i64>333; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub <2 x i64> [[ARG1_SEXT]], [[ARG0_SEXT]]334; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[SUB_NSW]])335; CHECK-NEXT: ret <2 x i64> [[SUB_SEXT]]336;337entry:338 %sub.nsw = sub nsw <2 x i32> %arg0, %arg1339 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>340 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>341 %sub.sext = sub <2 x i64> %arg1.sext, %arg0.sext342 call void @use.v2i32(<2 x i32> %sub.nsw)343 ret <2 x i64> %sub.sext344}345 346; Missing nsw on the add <2 x i32>, can't do anything347define <2 x i64> @add_sext__dominating_add_vector(<2 x i32> %arg0, <2 x i32> %arg1) {348; CHECK-LABEL: define <2 x i64> @add_sext__dominating_add_vector349; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {350; CHECK-NEXT: entry:351; CHECK-NEXT: [[ADD_NSW:%.*]] = add <2 x i32> [[ARG0]], [[ARG1]]352; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext <2 x i32> [[ARG0]] to <2 x i64>353; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext <2 x i32> [[ARG1]] to <2 x i64>354; CHECK-NEXT: [[ADD_SEXT:%.*]] = add <2 x i64> [[ARG0_SEXT]], [[ARG1_SEXT]]355; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[ADD_NSW]])356; CHECK-NEXT: ret <2 x i64> [[ADD_SEXT]]357;358entry:359 %add.nsw = add <2 x i32> %arg0, %arg1360 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>361 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>362 %add.sext = add <2 x i64> %arg0.sext, %arg1.sext363 call void @use.v2i32(<2 x i32> %add.nsw)364 ret <2 x i64> %add.sext365}366 367; Missing nsw on the sub <2 x i32>, can't do anything368define <2 x i64> @sub_sext__dominating_sub_vector(<2 x i32> %arg0, <2 x i32> %arg1) {369; CHECK-LABEL: define <2 x i64> @sub_sext__dominating_sub_vector370; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {371; CHECK-NEXT: entry:372; CHECK-NEXT: [[SUB_NSW:%.*]] = sub <2 x i32> [[ARG0]], [[ARG1]]373; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext <2 x i32> [[ARG0]] to <2 x i64>374; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext <2 x i32> [[ARG1]] to <2 x i64>375; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub <2 x i64> [[ARG0_SEXT]], [[ARG1_SEXT]]376; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[SUB_NSW]])377; CHECK-NEXT: ret <2 x i64> [[SUB_SEXT]]378;379entry:380 %sub.nsw = sub <2 x i32> %arg0, %arg1381 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>382 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>383 %sub.sext = sub <2 x i64> %arg0.sext, %arg1.sext384 call void @use.v2i32(<2 x i32> %sub.nsw)385 ret <2 x i64> %sub.sext386}387 388; The use of the 32-bit add allows poison, so can't fold.389define <2 x i64> @add_sext__dominating_add_nsw_defined_vector(<2 x i32> %arg0, <2 x i32> %arg1) {390; CHECK-LABEL: define <2 x i64> @add_sext__dominating_add_nsw_defined_vector391; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {392; CHECK-NEXT: entry:393; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw <2 x i32> [[ARG0]], [[ARG1]]394; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext <2 x i32> [[ARG0]] to <2 x i64>395; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext <2 x i32> [[ARG1]] to <2 x i64>396; CHECK-NEXT: [[ADD_SEXT:%.*]] = add <2 x i64> [[ARG0_SEXT]], [[ARG1_SEXT]]397; CHECK-NEXT: call void @allow.undef.use.v2i32(<2 x i32> [[ADD_NSW]])398; CHECK-NEXT: ret <2 x i64> [[ADD_SEXT]]399;400entry:401 %add.nsw = add nsw <2 x i32> %arg0, %arg1402 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>403 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>404 %add.sext = add <2 x i64> %arg0.sext, %arg1.sext405 call void @allow.undef.use.v2i32(<2 x i32> %add.nsw)406 ret <2 x i64> %add.sext407}408 409; The use of the 32-bit sub allows poison, so can't fold.410define <2 x i64> @sub_sext__dominating_sub_nsw_defined_vector(<2 x i32> %arg0, <2 x i32> %arg1) {411; CHECK-LABEL: define <2 x i64> @sub_sext__dominating_sub_nsw_defined_vector412; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {413; CHECK-NEXT: entry:414; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw <2 x i32> [[ARG0]], [[ARG1]]415; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext <2 x i32> [[ARG0]] to <2 x i64>416; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext <2 x i32> [[ARG1]] to <2 x i64>417; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub <2 x i64> [[ARG0_SEXT]], [[ARG1_SEXT]]418; CHECK-NEXT: call void @allow.undef.use.v2i32(<2 x i32> [[SUB_NSW]])419; CHECK-NEXT: ret <2 x i64> [[SUB_SEXT]]420;421entry:422 %sub.nsw = sub nsw <2 x i32> %arg0, %arg1423 %arg0.sext = sext <2 x i32> %arg0 to <2 x i64>424 %arg1.sext = sext <2 x i32> %arg1 to <2 x i64>425 %sub.sext = sub <2 x i64> %arg0.sext, %arg1.sext426 call void @allow.undef.use.v2i32(<2 x i32> %sub.nsw)427 ret <2 x i64> %sub.sext428}429 430; --------------------------------------------------------------------431; Zext x nsw432; --------------------------------------------------------------------433 434; Want sext, not zext435define i64 @add_zext__dominating_add_nsw(i32 %arg0, i32 %arg1) {436; CHECK-LABEL: define i64 @add_zext__dominating_add_nsw437; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {438; CHECK-NEXT: entry:439; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]440; CHECK-NEXT: [[ARG0_SEXT:%.*]] = zext i32 [[ARG0]] to i64441; CHECK-NEXT: [[ARG1_SEXT:%.*]] = zext i32 [[ARG1]] to i64442; CHECK-NEXT: [[ADD_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]443; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])444; CHECK-NEXT: ret i64 [[ADD_SEXT]]445;446entry:447 %add.nsw = add nsw i32 %arg0, %arg1448 %arg0.sext = zext i32 %arg0 to i64449 %arg1.sext = zext i32 %arg1 to i64450 %add.sext = add i64 %arg0.sext, %arg1.sext451 call void @use.i32(i32 %add.nsw)452 ret i64 %add.sext453}454 455; Want sext, not zext456define i64 @sub_zext__dominating_add_nsw(i32 %arg0, i32 %arg1) {457; CHECK-LABEL: define i64 @sub_zext__dominating_add_nsw458; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {459; CHECK-NEXT: entry:460; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]461; CHECK-NEXT: [[ARG0_SEXT:%.*]] = zext i32 [[ARG0]] to i64462; CHECK-NEXT: [[ARG1_SEXT:%.*]] = zext i32 [[ARG1]] to i64463; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]464; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])465; CHECK-NEXT: ret i64 [[SUB_SEXT]]466;467entry:468 %sub.nsw = sub nsw i32 %arg0, %arg1469 %arg0.sext = zext i32 %arg0 to i64470 %arg1.sext = zext i32 %arg1 to i64471 %sub.sext = sub i64 %arg0.sext, %arg1.sext472 call void @use.i32(i32 %sub.nsw)473 ret i64 %sub.sext474}475 476; --------------------------------------------------------------------477; sext x nuw478; --------------------------------------------------------------------479 480; Want nsw, not nuw481define i64 @add_sext__dominating_add_nuw(i32 %arg0, i32 %arg1) {482; CHECK-LABEL: define i64 @add_sext__dominating_add_nuw483; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {484; CHECK-NEXT: entry:485; CHECK-NEXT: [[ADD_NUW:%.*]] = add nuw i32 [[ARG0]], [[ARG1]]486; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64487; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64488; CHECK-NEXT: [[ADD_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]489; CHECK-NEXT: call void @use.i32(i32 [[ADD_NUW]])490; CHECK-NEXT: ret i64 [[ADD_SEXT]]491;492entry:493 %add.nuw = add nuw i32 %arg0, %arg1494 %arg0.sext = sext i32 %arg0 to i64495 %arg1.sext = sext i32 %arg1 to i64496 %add.sext = add i64 %arg0.sext, %arg1.sext497 call void @use.i32(i32 %add.nuw)498 ret i64 %add.sext499}500 501; Want nsw, not nuw502define i64 @sub_sext__dominating_sub_nuw(i32 %arg0, i32 %arg1) {503; CHECK-LABEL: define i64 @sub_sext__dominating_sub_nuw504; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {505; CHECK-NEXT: entry:506; CHECK-NEXT: [[SUB_NUW:%.*]] = sub nuw i32 [[ARG0]], [[ARG1]]507; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64508; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64509; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]510; CHECK-NEXT: call void @use.i32(i32 [[SUB_NUW]])511; CHECK-NEXT: ret i64 [[SUB_SEXT]]512;513entry:514 %sub.nuw = sub nuw i32 %arg0, %arg1515 %arg0.sext = sext i32 %arg0 to i64516 %arg1.sext = sext i32 %arg1 to i64517 %sub.sext = sub i64 %arg0.sext, %arg1.sext518 call void @use.i32(i32 %sub.nuw)519 ret i64 %sub.sext520}521 522; --------------------------------------------------------------------523; Misc negative tests524; --------------------------------------------------------------------525 526; Opcode mismatch 1527define i64 @add_sext__dominating_sub_nsw(i32 %arg0, i32 %arg1) {528; CHECK-LABEL: define i64 @add_sext__dominating_sub_nsw529; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {530; CHECK-NEXT: entry:531; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]532; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64533; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64534; CHECK-NEXT: [[SUB_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]535; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])536; CHECK-NEXT: ret i64 [[SUB_SEXT]]537;538entry:539 %sub.nsw = sub nsw i32 %arg0, %arg1540 %arg0.sext = sext i32 %arg0 to i64541 %arg1.sext = sext i32 %arg1 to i64542 %sub.sext = add i64 %arg0.sext, %arg1.sext543 call void @use.i32(i32 %sub.nsw)544 ret i64 %sub.sext545}546 547; Opcode mismatch 2548define i64 @sub_sext__dominating_add_nsw(i32 %arg0, i32 %arg1) {549; CHECK-LABEL: define i64 @sub_sext__dominating_add_nsw550; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {551; CHECK-NEXT: entry:552; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]553; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64554; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64555; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]556; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])557; CHECK-NEXT: ret i64 [[SUB_SEXT]]558;559entry:560 %add.nsw = add nsw i32 %arg0, %arg1561 %arg0.sext = sext i32 %arg0 to i64562 %arg1.sext = sext i32 %arg1 to i64563 %sub.sext = sub i64 %arg0.sext, %arg1.sext564 call void @use.i32(i32 %add.nsw)565 ret i64 %sub.sext566}567 568; Both nsw add and sub coexist for the same inputs569define void @add_sext__dominating_add_nsw_sub_nsw(i32 %arg0, i32 %arg1) {570; CHECK-LABEL: define void @add_sext__dominating_add_nsw_sub_nsw571; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {572; CHECK-NEXT: entry:573; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]574; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]575; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64576; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64577; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext i32 [[ADD_NSW]] to i64578; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]579; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])580; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])581; CHECK-NEXT: call void @use.i64(i64 [[ADD_SEXT]])582; CHECK-NEXT: call void @use.i64(i64 [[SUB_SEXT]])583; CHECK-NEXT: ret void584;585entry:586 %add.nsw = add nsw i32 %arg0, %arg1587 %sub.nsw = sub nsw i32 %arg0, %arg1588 %arg0.sext = sext i32 %arg0 to i64589 %arg1.sext = sext i32 %arg1 to i64590 %add.sext = add i64 %arg0.sext, %arg1.sext591 %sub.sext = sub i64 %arg0.sext, %arg1.sext592 call void @use.i32(i32 %add.nsw)593 call void @use.i32(i32 %sub.nsw)594 call void @use.i64(i64 %add.sext)595 call void @use.i64(i64 %sub.sext)596 ret void597}598 599; Both nsw add and sub coexist for the same inputs, but commuted600define void @add_sext__dominating_add_nsw_sub_nsw_swapped(i32 %arg0, i32 %arg1) {601; CHECK-LABEL: define void @add_sext__dominating_add_nsw_sub_nsw_swapped602; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {603; CHECK-NEXT: entry:604; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]605; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG1]], [[ARG0]]606; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64607; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64608; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext i32 [[ADD_NSW]] to i64609; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG1_SEXT]], [[ARG0_SEXT]]610; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])611; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])612; CHECK-NEXT: call void @use.i64(i64 [[ADD_SEXT]])613; CHECK-NEXT: call void @use.i64(i64 [[SUB_SEXT]])614; CHECK-NEXT: ret void615;616entry:617 %add.nsw = add nsw i32 %arg0, %arg1618 %sub.nsw = sub nsw i32 %arg1, %arg0619 %arg0.sext = sext i32 %arg0 to i64620 %arg1.sext = sext i32 %arg1 to i64621 %add.sext = add i64 %arg0.sext, %arg1.sext622 %sub.sext = sub i64 %arg1.sext, %arg0.sext623 call void @use.i32(i32 %add.nsw)624 call void @use.i32(i32 %sub.nsw)625 call void @use.i64(i64 %add.sext)626 call void @use.i64(i64 %sub.sext)627 ret void628}629 630; --------------------------------------------------------------------631; zext x nuw632; --------------------------------------------------------------------633 634; Should fold out the add i64635define i64 @add_zext__dominating_add_nuw(i32 %arg0, i32 %arg1) {636; CHECK-LABEL: define i64 @add_zext__dominating_add_nuw637; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {638; CHECK-NEXT: entry:639; CHECK-NEXT: [[ADD_NUW:%.*]] = add nuw i32 [[ARG0]], [[ARG1]]640; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64641; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64642; CHECK-NEXT: [[ADD_ZEXT:%.*]] = add i64 [[ARG0_ZEXT]], [[ARG1_ZEXT]]643; CHECK-NEXT: call void @use.i32(i32 [[ADD_NUW]])644; CHECK-NEXT: ret i64 [[ADD_ZEXT]]645;646entry:647 %add.nuw = add nuw i32 %arg0, %arg1648 %arg0.zext = zext i32 %arg0 to i64649 %arg1.zext = zext i32 %arg1 to i64650 %add.zext = add i64 %arg0.zext, %arg1.zext651 call void @use.i32(i32 %add.nuw)652 ret i64 %add.zext653}654 655; Should fold out the sub i64656define i64 @sub_zext__dominating_sub_nuw(i32 %arg0, i32 %arg1) {657; CHECK-LABEL: define i64 @sub_zext__dominating_sub_nuw658; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {659; CHECK-NEXT: entry:660; CHECK-NEXT: [[SUB_NUW:%.*]] = sub nuw i32 [[ARG0]], [[ARG1]]661; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64662; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64663; CHECK-NEXT: [[SUB_ZEXT:%.*]] = sub i64 [[ARG0_ZEXT]], [[ARG1_ZEXT]]664; CHECK-NEXT: call void @use.i32(i32 [[SUB_NUW]])665; CHECK-NEXT: ret i64 [[SUB_ZEXT]]666;667entry:668 %sub.nuw = sub nuw i32 %arg0, %arg1669 %arg0.zext = zext i32 %arg0 to i64670 %arg1.zext = zext i32 %arg1 to i64671 %sub.zext = sub i64 %arg0.zext, %arg1.zext672 call void @use.i32(i32 %sub.nuw)673 ret i64 %sub.zext674}675 676; Should fold out the add <2 x i64>677define <2 x i64> @add_zext__dominating_add_nuw_vector(<2 x i32> %arg0, <2 x i32> %arg1) {678; CHECK-LABEL: define <2 x i64> @add_zext__dominating_add_nuw_vector679; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {680; CHECK-NEXT: entry:681; CHECK-NEXT: [[ADD_NUW:%.*]] = add nuw <2 x i32> [[ARG0]], [[ARG1]]682; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext <2 x i32> [[ARG0]] to <2 x i64>683; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext <2 x i32> [[ARG1]] to <2 x i64>684; CHECK-NEXT: [[ADD_ZEXT:%.*]] = add <2 x i64> [[ARG0_ZEXT]], [[ARG1_ZEXT]]685; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[ADD_NUW]])686; CHECK-NEXT: ret <2 x i64> [[ADD_ZEXT]]687;688entry:689 %add.nuw = add nuw <2 x i32> %arg0, %arg1690 %arg0.zext = zext <2 x i32> %arg0 to <2 x i64>691 %arg1.zext = zext <2 x i32> %arg1 to <2 x i64>692 %add.zext = add <2 x i64> %arg0.zext, %arg1.zext693 call void @use.v2i32(<2 x i32> %add.nuw)694 ret <2 x i64> %add.zext695}696 697; Should fold out the sub <2 x i64>698define <2 x i64> @sub_zext__dominating_sub_nuw_vector(<2 x i32> %arg0, <2 x i32> %arg1) {699; CHECK-LABEL: define <2 x i64> @sub_zext__dominating_sub_nuw_vector700; CHECK-SAME: (<2 x i32> [[ARG0:%.*]], <2 x i32> [[ARG1:%.*]]) #[[ATTR0]] {701; CHECK-NEXT: entry:702; CHECK-NEXT: [[SUB_NUW:%.*]] = sub nuw <2 x i32> [[ARG0]], [[ARG1]]703; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext <2 x i32> [[ARG0]] to <2 x i64>704; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext <2 x i32> [[ARG1]] to <2 x i64>705; CHECK-NEXT: [[SUB_ZEXT:%.*]] = sub <2 x i64> [[ARG0_ZEXT]], [[ARG1_ZEXT]]706; CHECK-NEXT: call void @use.v2i32(<2 x i32> [[SUB_NUW]])707; CHECK-NEXT: ret <2 x i64> [[SUB_ZEXT]]708;709entry:710 %sub.nuw = sub nuw <2 x i32> %arg0, %arg1711 %arg0.zext = zext <2 x i32> %arg0 to <2 x i64>712 %arg1.zext = zext <2 x i32> %arg1 to <2 x i64>713 %sub.zext = sub <2 x i64> %arg0.zext, %arg1.zext714 call void @use.v2i32(<2 x i32> %sub.nuw)715 ret <2 x i64> %sub.zext716}717 718; Both nuw and nsw exist719define void @add_zext_add_sext__dominating_add_nuw_add_nsw(i32 %arg0, i32 %arg1) {720; CHECK-LABEL: define void @add_zext_add_sext__dominating_add_nuw_add_nsw721; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {722; CHECK-NEXT: entry:723; CHECK-NEXT: [[ADD_NUW:%.*]] = add nuw i32 [[ARG0]], [[ARG1]]724; CHECK-NEXT: [[ADD_NSW:%.*]] = add nsw i32 [[ARG0]], [[ARG1]]725; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64726; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64727; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64728; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64729; CHECK-NEXT: [[ADD_ZEXT:%.*]] = add i64 [[ARG0_ZEXT]], [[ARG1_ZEXT]]730; CHECK-NEXT: [[ADD_SEXT:%.*]] = add i64 [[ARG0_SEXT]], [[ARG1_SEXT]]731; CHECK-NEXT: call void @use.i32(i32 [[ADD_NUW]])732; CHECK-NEXT: call void @use.i32(i32 [[ADD_NSW]])733; CHECK-NEXT: call void @use.i64(i64 [[ADD_ZEXT]])734; CHECK-NEXT: call void @use.i64(i64 [[ADD_SEXT]])735; CHECK-NEXT: ret void736;737entry:738 %add.nuw = add nuw i32 %arg0, %arg1739 %add.nsw = add nsw i32 %arg0, %arg1740 %arg0.zext = zext i32 %arg0 to i64741 %arg1.zext = zext i32 %arg1 to i64742 %arg0.sext = sext i32 %arg0 to i64743 %arg1.sext = sext i32 %arg1 to i64744 %add.zext = add i64 %arg0.zext, %arg1.zext745 %add.sext = add i64 %arg0.sext, %arg1.sext746 call void @use.i32(i32 %add.nuw)747 call void @use.i32(i32 %add.nsw)748 call void @use.i64(i64 %add.zext)749 call void @use.i64(i64 %add.sext)750 ret void751}752 753; Both exist754define void @sub_zext_sub_sext__dominating_sub_nuw_sub_nsw(i32 %arg0, i32 %arg1) {755; CHECK-LABEL: define void @sub_zext_sub_sext__dominating_sub_nuw_sub_nsw756; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {757; CHECK-NEXT: entry:758; CHECK-NEXT: [[SUB_NUW:%.*]] = sub nuw i32 [[ARG0]], [[ARG1]]759; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG0]], [[ARG1]]760; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64761; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64762; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64763; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64764; CHECK-NEXT: [[SUB_ZEXT:%.*]] = sub i64 [[ARG0_ZEXT]], [[ARG1_ZEXT]]765; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]766; CHECK-NEXT: call void @use.i32(i32 [[SUB_NUW]])767; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])768; CHECK-NEXT: call void @use.i64(i64 [[SUB_ZEXT]])769; CHECK-NEXT: call void @use.i64(i64 [[SUB_SEXT]])770; CHECK-NEXT: ret void771;772entry:773 %sub.nuw = sub nuw i32 %arg0, %arg1774 %sub.nsw = sub nsw i32 %arg0, %arg1775 %arg0.zext = zext i32 %arg0 to i64776 %arg1.zext = zext i32 %arg1 to i64777 %arg0.sext = sext i32 %arg0 to i64778 %arg1.sext = sext i32 %arg1 to i64779 %sub.zext = sub i64 %arg0.zext, %arg1.zext780 %sub.sext = sub i64 %arg0.sext, %arg1.sext781 call void @use.i32(i32 %sub.nuw)782 call void @use.i32(i32 %sub.nsw)783 call void @use.i64(i64 %sub.zext)784 call void @use.i64(i64 %sub.sext)785 ret void786}787 788; Both exist with commuted operands from each other789define void @sub_zext_sub_sext__dominating_sub_nuw_sub_nsw_commuted(i32 %arg0, i32 %arg1) {790; CHECK-LABEL: define void @sub_zext_sub_sext__dominating_sub_nuw_sub_nsw_commuted791; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {792; CHECK-NEXT: entry:793; CHECK-NEXT: [[SUB_NUW:%.*]] = sub nuw i32 [[ARG0]], [[ARG1]]794; CHECK-NEXT: [[SUB_NSW:%.*]] = sub nsw i32 [[ARG1]], [[ARG0]]795; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64796; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64797; CHECK-NEXT: [[ARG0_SEXT:%.*]] = sext i32 [[ARG0]] to i64798; CHECK-NEXT: [[ARG1_SEXT:%.*]] = sext i32 [[ARG1]] to i64799; CHECK-NEXT: [[SUB_ZEXT:%.*]] = sub i64 [[ARG0_ZEXT]], [[ARG1_ZEXT]]800; CHECK-NEXT: [[SUB_SEXT:%.*]] = sub i64 [[ARG0_SEXT]], [[ARG1_SEXT]]801; CHECK-NEXT: call void @use.i32(i32 [[SUB_NUW]])802; CHECK-NEXT: call void @use.i32(i32 [[SUB_NSW]])803; CHECK-NEXT: call void @use.i64(i64 [[SUB_ZEXT]])804; CHECK-NEXT: call void @use.i64(i64 [[SUB_SEXT]])805; CHECK-NEXT: ret void806;807entry:808 %sub.nuw = sub nuw i32 %arg0, %arg1809 %sub.nsw = sub nsw i32 %arg1, %arg0810 %arg0.zext = zext i32 %arg0 to i64811 %arg1.zext = zext i32 %arg1 to i64812 %arg0.sext = sext i32 %arg0 to i64813 %arg1.sext = sext i32 %arg1 to i64814 %sub.zext = sub i64 %arg0.zext, %arg1.zext815 %sub.sext = sub i64 %arg0.sext, %arg1.sext816 call void @use.i32(i32 %sub.nuw)817 call void @use.i32(i32 %sub.nsw)818 call void @use.i64(i64 %sub.zext)819 call void @use.i64(i64 %sub.sext)820 ret void821}822 823; --------------------------------------------------------------------824; zext x nuw+nsw825; --------------------------------------------------------------------826 827; Should fold out the add i64828define i64 @add_zext__dominating_add_nuw_nsw(i32 %arg0, i32 %arg1) {829; CHECK-LABEL: define i64 @add_zext__dominating_add_nuw_nsw830; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {831; CHECK-NEXT: entry:832; CHECK-NEXT: [[ADD_NUW_NSW:%.*]] = add nuw nsw i32 [[ARG0]], [[ARG1]]833; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64834; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64835; CHECK-NEXT: [[ADD_ZEXT:%.*]] = add i64 [[ARG0_ZEXT]], [[ARG1_ZEXT]]836; CHECK-NEXT: call void @use.i32(i32 [[ADD_NUW_NSW]])837; CHECK-NEXT: ret i64 [[ADD_ZEXT]]838;839entry:840 %add.nuw.nsw = add nuw nsw i32 %arg0, %arg1841 %arg0.zext = zext i32 %arg0 to i64842 %arg1.zext = zext i32 %arg1 to i64843 %add.zext = add i64 %arg0.zext, %arg1.zext844 call void @use.i32(i32 %add.nuw.nsw)845 ret i64 %add.zext846}847 848; Should fold out the add i64849define i64 @add_zext__dominating_add_nuw_nsw_commute(i32 %arg0, i32 %arg1) {850; CHECK-LABEL: define i64 @add_zext__dominating_add_nuw_nsw_commute851; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {852; CHECK-NEXT: entry:853; CHECK-NEXT: [[ADD_NUW_NSW:%.*]] = add nuw nsw i32 [[ARG0]], [[ARG1]]854; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64855; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64856; CHECK-NEXT: [[ADD_ZEXT:%.*]] = add i64 [[ARG1_ZEXT]], [[ARG0_ZEXT]]857; CHECK-NEXT: call void @use.i32(i32 [[ADD_NUW_NSW]])858; CHECK-NEXT: ret i64 [[ADD_ZEXT]]859;860entry:861 %add.nuw.nsw = add nuw nsw i32 %arg0, %arg1862 %arg0.zext = zext i32 %arg0 to i64863 %arg1.zext = zext i32 %arg1 to i64864 %add.zext = add i64 %arg1.zext, %arg0.zext865 call void @use.i32(i32 %add.nuw.nsw)866 ret i64 %add.zext867}868 869; Should fold out the sub i64870define i64 @sub_zext__dominating_sub_nuw_esw(i32 %arg0, i32 %arg1) {871; CHECK-LABEL: define i64 @sub_zext__dominating_sub_nuw_esw872; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {873; CHECK-NEXT: entry:874; CHECK-NEXT: [[SUB_NUW:%.*]] = sub nuw nsw i32 [[ARG0]], [[ARG1]]875; CHECK-NEXT: [[ARG0_ZEXT:%.*]] = zext i32 [[ARG0]] to i64876; CHECK-NEXT: [[ARG1_ZEXT:%.*]] = zext i32 [[ARG1]] to i64877; CHECK-NEXT: [[SUB_ZEXT:%.*]] = sub i64 [[ARG0_ZEXT]], [[ARG1_ZEXT]]878; CHECK-NEXT: call void @use.i32(i32 [[SUB_NUW]])879; CHECK-NEXT: ret i64 [[SUB_ZEXT]]880;881entry:882 %sub.nuw = sub nuw nsw i32 %arg0, %arg1883 %arg0.zext = zext i32 %arg0 to i64884 %arg1.zext = zext i32 %arg1 to i64885 %sub.zext = sub i64 %arg0.zext, %arg1.zext886 call void @use.i32(i32 %sub.nuw)887 ret i64 %sub.zext888}889 890; --------------------------------------------------------------------891; sext x nuw+nsw892; --------------------------------------------------------------------893 894; Should fold out the add i64895define i64 @add_sext__dominating_add_nuw_nsw(i32 %arg0, i32 %arg1) {896; CHECK-LABEL: define i64 @add_sext__dominating_add_nuw_nsw897; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {898; CHECK-NEXT: entry:899; CHECK-NEXT: [[ADD_NUW_NSW:%.*]] = add nuw nsw i32 [[ARG0]], [[ARG1]]900; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext i32 [[ADD_NUW_NSW]] to i64901; CHECK-NEXT: call void @use.i32(i32 [[ADD_NUW_NSW]])902; CHECK-NEXT: ret i64 [[ADD_SEXT]]903;904entry:905 %add.nuw.nsw = add nuw nsw i32 %arg0, %arg1906 %arg0.sext = sext i32 %arg0 to i64907 %arg1.sext = sext i32 %arg1 to i64908 %add.sext = add i64 %arg0.sext, %arg1.sext909 call void @use.i32(i32 %add.nuw.nsw)910 ret i64 %add.sext911}912 913; Should fold out the add i64914define i64 @add_sext__dominating_add_nuw_nsw_commute(i32 %arg0, i32 %arg1) {915; CHECK-LABEL: define i64 @add_sext__dominating_add_nuw_nsw_commute916; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {917; CHECK-NEXT: entry:918; CHECK-NEXT: [[ADD_NUW_NSW:%.*]] = add nuw nsw i32 [[ARG0]], [[ARG1]]919; CHECK-NEXT: [[ADD_SEXT:%.*]] = sext i32 [[ADD_NUW_NSW]] to i64920; CHECK-NEXT: call void @use.i32(i32 [[ADD_NUW_NSW]])921; CHECK-NEXT: ret i64 [[ADD_SEXT]]922;923entry:924 %add.nuw.nsw = add nuw nsw i32 %arg0, %arg1925 %arg0.sext = sext i32 %arg0 to i64926 %arg1.sext = sext i32 %arg1 to i64927 %add.sext = add i64 %arg1.sext, %arg0.sext928 call void @use.i32(i32 %add.nuw.nsw)929 ret i64 %add.sext930}931 932; Should fold out the sub i64933define i64 @sub_sext__dominating_sub_nuw_esw(i32 %arg0, i32 %arg1) {934; CHECK-LABEL: define i64 @sub_sext__dominating_sub_nuw_esw935; CHECK-SAME: (i32 [[ARG0:%.*]], i32 [[ARG1:%.*]]) #[[ATTR0]] {936; CHECK-NEXT: entry:937; CHECK-NEXT: [[SUB_NUW:%.*]] = sub nuw nsw i32 [[ARG0]], [[ARG1]]938; CHECK-NEXT: [[SUB_SEXT:%.*]] = sext i32 [[SUB_NUW]] to i64939; CHECK-NEXT: call void @use.i32(i32 [[SUB_NUW]])940; CHECK-NEXT: ret i64 [[SUB_SEXT]]941;942entry:943 %sub.nuw = sub nuw nsw i32 %arg0, %arg1944 %arg0.sext = sext i32 %arg0 to i64945 %arg1.sext = sext i32 %arg1 to i64946 %sub.sext = sub i64 %arg0.sext, %arg1.sext947 call void @use.i32(i32 %sub.nuw)948 ret i64 %sub.sext949}950