1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -passes='reassociate' -S < %s | FileCheck %s --check-prefix=REASSOCIATE_ONLY 3; RUN: opt -passes='licm' -S < %s | FileCheck %s --check-prefix=LICM_ONLY 4; RUN: opt -passes='licm' -licm-max-num-fp-reassociations=1 -S < %s | FileCheck %s --check-prefix=LICM_ONLY_CONSTRAINED 5; RUN: opt -passes='reassociate,loop-mssa(licm)' -S < %s | FileCheck %s --check-prefix=LICM_AFTER_REASSOCIATE 6; RUN: opt -passes='reassociate,loop-mssa(licm)' -licm-max-num-fp-reassociations=1 -S < %s | FileCheck %s --check-prefix=LICM_AFTER_REASSOCIATE_CONSTRAINED 7 8; 9; A simple loop, should not get modified: 10; 11; int j; 12; const double d1d = d1 * delta; 13; 14; for (j = 0; j <= i; j++) 15; cells[j] = d1d * cells[j + 1]; 16; 17 18define void @innermost_loop_1d_fast(i32 %i, double %d1, double %delta, ptr %cells) { 19; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_1d_fast 20; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 21; REASSOCIATE_ONLY-NEXT: entry: 22; REASSOCIATE_ONLY-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[DELTA]], [[D1]] 23; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 24; REASSOCIATE_ONLY: for.cond: 25; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 26; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 27; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 28; REASSOCIATE_ONLY: for.body: 29; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 30; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 31; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 32; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 33; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 34; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 35; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 36; REASSOCIATE_ONLY-NEXT: store double [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 37; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 38; REASSOCIATE_ONLY: for.end: 39; REASSOCIATE_ONLY-NEXT: ret void 40; 41; LICM_ONLY-LABEL: define void @innermost_loop_1d_fast 42; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 43; LICM_ONLY-NEXT: entry: 44; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[D1]], [[DELTA]] 45; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 46; LICM_ONLY: for.cond: 47; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 48; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 49; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 50; LICM_ONLY: for.body: 51; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 52; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 53; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 54; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 55; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 56; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 57; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 58; LICM_ONLY-NEXT: store double [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 59; LICM_ONLY-NEXT: br label [[FOR_COND]] 60; LICM_ONLY: for.end: 61; LICM_ONLY-NEXT: ret void 62; 63; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_1d_fast 64; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 65; LICM_ONLY_CONSTRAINED-NEXT: entry: 66; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[D1]], [[DELTA]] 67; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 68; LICM_ONLY_CONSTRAINED: for.cond: 69; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 70; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 71; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 72; LICM_ONLY_CONSTRAINED: for.body: 73; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 74; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 75; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 76; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 77; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 78; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 79; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 80; LICM_ONLY_CONSTRAINED-NEXT: store double [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 81; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 82; LICM_ONLY_CONSTRAINED: for.end: 83; LICM_ONLY_CONSTRAINED-NEXT: ret void 84; 85; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_1d_fast 86; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 87; LICM_AFTER_REASSOCIATE-NEXT: entry: 88; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[DELTA]], [[D1]] 89; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 90; LICM_AFTER_REASSOCIATE: for.cond: 91; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 92; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 93; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 94; LICM_AFTER_REASSOCIATE: for.body: 95; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 96; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 97; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 98; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 99; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 100; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 101; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 102; LICM_AFTER_REASSOCIATE-NEXT: store double [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 103; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 104; LICM_AFTER_REASSOCIATE: for.end: 105; LICM_AFTER_REASSOCIATE-NEXT: ret void 106; 107; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_1d_fast 108; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 109; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 110; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[DELTA]], [[D1]] 111; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 112; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 113; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 114; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 115; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 116; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 117; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 118; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 119; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 120; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 121; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 122; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 123; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 124; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 125; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 126; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 127; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 128; 129entry: 130 %fmul.d1 = fmul fast double %d1, %delta 131 br label %for.cond 132 133for.cond: 134 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 135 %cmp.not = icmp sgt i32 %j, %i 136 br i1 %cmp.not, label %for.end, label %for.body 137 138for.body: 139 %add.j.1 = add nuw nsw i32 %j, 1 140 %idxprom.j.1 = zext i32 %add.j.1 to i64 141 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 142 %cell.1 = load double, ptr %arrayidx.j.1, align 8 143 %fmul.1 = fmul fast double %fmul.d1, %cell.1 144 %idxprom.j = zext i32 %j to i64 145 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 146 store double %fmul.1, ptr %arrayidx.j, align 8 147 br label %for.cond 148 149for.end: 150 ret void 151} 152 153; 154; A simple loop: 155; 156; int j; 157; 158; for (j = 0; j <= i; j++) 159; cells[j] = d1 * cells[j + 1] * delta; 160; 161; ...should be transformed by the LICM pass into this: 162; 163; int j; 164; const double d1d = d1 * delta; 165; 166; for (j = 0; j <= i; j++) 167; cells[j] = d1d * cells[j + 1]; 168; 169 170define void @innermost_loop_1d_shouldhoist_fast(i32 %i, double %d1, double %delta, ptr %cells) { 171; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_1d_shouldhoist_fast 172; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 173; REASSOCIATE_ONLY-NEXT: entry: 174; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 175; REASSOCIATE_ONLY: for.cond: 176; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 177; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 178; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 179; REASSOCIATE_ONLY: for.body: 180; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 181; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 182; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 183; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 184; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[DELTA]], [[D1]] 185; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[FMUL_1]], [[CELL_1]] 186; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 187; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 188; REASSOCIATE_ONLY-NEXT: store double [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 189; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 190; REASSOCIATE_ONLY: for.end: 191; REASSOCIATE_ONLY-NEXT: ret void 192; 193; LICM_ONLY-LABEL: define void @innermost_loop_1d_shouldhoist_fast 194; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 195; LICM_ONLY-NEXT: entry: 196; LICM_ONLY-NEXT: [[FACTOR_OP_FMUL:%.*]] = fmul fast double [[D1]], [[DELTA]] 197; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 198; LICM_ONLY: for.cond: 199; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 200; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 201; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 202; LICM_ONLY: for.body: 203; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 204; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 205; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 206; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 207; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FACTOR_OP_FMUL]], [[CELL_1]] 208; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 209; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 210; LICM_ONLY-NEXT: store double [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 211; LICM_ONLY-NEXT: br label [[FOR_COND]] 212; LICM_ONLY: for.end: 213; LICM_ONLY-NEXT: ret void 214; 215; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_1d_shouldhoist_fast 216; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 217; LICM_ONLY_CONSTRAINED-NEXT: entry: 218; LICM_ONLY_CONSTRAINED-NEXT: [[FACTOR_OP_FMUL:%.*]] = fmul fast double [[D1]], [[DELTA]] 219; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 220; LICM_ONLY_CONSTRAINED: for.cond: 221; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 222; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 223; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 224; LICM_ONLY_CONSTRAINED: for.body: 225; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 226; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 227; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 228; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 229; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FACTOR_OP_FMUL]], [[CELL_1]] 230; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 231; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 232; LICM_ONLY_CONSTRAINED-NEXT: store double [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 233; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 234; LICM_ONLY_CONSTRAINED: for.end: 235; LICM_ONLY_CONSTRAINED-NEXT: ret void 236; 237; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_1d_shouldhoist_fast 238; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 239; LICM_AFTER_REASSOCIATE-NEXT: entry: 240; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul fast double [[DELTA]], [[D1]] 241; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 242; LICM_AFTER_REASSOCIATE: for.cond: 243; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 244; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 245; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 246; LICM_AFTER_REASSOCIATE: for.body: 247; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 248; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 249; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 250; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 251; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul fast double [[FMUL_1]], [[CELL_1]] 252; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 253; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 254; LICM_AFTER_REASSOCIATE-NEXT: store double [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 255; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 256; LICM_AFTER_REASSOCIATE: for.end: 257; LICM_AFTER_REASSOCIATE-NEXT: ret void 258; 259; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_1d_shouldhoist_fast 260; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 261; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 262; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[DELTA]], [[D1]] 263; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 264; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 265; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 266; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 267; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 268; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 269; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 270; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 271; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 272; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 273; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[FMUL_1]], [[CELL_1]] 274; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 275; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 276; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 277; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 278; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 279; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 280; 281entry: 282 br label %for.cond 283 284for.cond: 285 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 286 %cmp.not = icmp sgt i32 %j, %i 287 br i1 %cmp.not, label %for.end, label %for.body 288 289for.body: 290 %add.j.1 = add nuw nsw i32 %j, 1 291 %idxprom.j.1 = zext i32 %add.j.1 to i64 292 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 293 %cell.1 = load double, ptr %arrayidx.j.1, align 8 294 %fmul.1 = fmul fast double %d1, %cell.1 295 %fmul.2 = fmul fast double %fmul.1, %delta 296 %idxprom.j = zext i32 %j to i64 297 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 298 store double %fmul.2, ptr %arrayidx.j, align 8 299 br label %for.cond 300 301for.end: 302 ret void 303} 304 305; 306; The following loop will be modified by the 'Reassociate expressions' pass, 307; 308; int j; 309; const double d1d = d1 * delta; 310; const double d2d = d2 * delta; 311; 312; for (j = 0; j <= i; j++) 313; cells[j] = d1d * cells[j + 1] + d2d * cells[j]; 314; 315; ...into this: 316; 317; int j; 318; 319; for (j = 0; j <= i; j++) 320; cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta; 321; 322; We expect the LICM pass to undo this transformation. 323; 324 325define void @innermost_loop_2d_fast(i32 %i, double %d1, double %d2, double %delta, ptr %cells) { 326; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d_fast 327; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 328; REASSOCIATE_ONLY-NEXT: entry: 329; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 330; REASSOCIATE_ONLY: for.cond: 331; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 332; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 333; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 334; REASSOCIATE_ONLY: for.body: 335; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 336; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 337; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 338; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 339; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 340; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 341; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 342; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 343; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[D2]] 344; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 345; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD]], [[DELTA]] 346; REASSOCIATE_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 347; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 348; REASSOCIATE_ONLY: for.end: 349; REASSOCIATE_ONLY-NEXT: ret void 350; 351; LICM_ONLY-LABEL: define void @innermost_loop_2d_fast 352; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 353; LICM_ONLY-NEXT: entry: 354; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[D1]], [[DELTA]] 355; LICM_ONLY-NEXT: [[FMUL_D2:%.*]] = fmul fast double [[D2]], [[DELTA]] 356; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 357; LICM_ONLY: for.cond: 358; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 359; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 360; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 361; LICM_ONLY: for.body: 362; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 363; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 364; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 365; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 366; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 367; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 368; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 369; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 370; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[FMUL_D2]], [[CELL_2]] 371; LICM_ONLY-NEXT: [[FADD_1:%.*]] = fadd fast double [[FMUL_1]], [[FMUL_2]] 372; LICM_ONLY-NEXT: store double [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 373; LICM_ONLY-NEXT: br label [[FOR_COND]] 374; LICM_ONLY: for.end: 375; LICM_ONLY-NEXT: ret void 376; 377; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d_fast 378; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 379; LICM_ONLY_CONSTRAINED-NEXT: entry: 380; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[D1]], [[DELTA]] 381; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = fmul fast double [[D2]], [[DELTA]] 382; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 383; LICM_ONLY_CONSTRAINED: for.cond: 384; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 385; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 386; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 387; LICM_ONLY_CONSTRAINED: for.body: 388; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 389; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 390; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 391; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 392; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 393; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 394; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 395; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 396; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[FMUL_D2]], [[CELL_2]] 397; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_1:%.*]] = fadd fast double [[FMUL_1]], [[FMUL_2]] 398; LICM_ONLY_CONSTRAINED-NEXT: store double [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 399; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 400; LICM_ONLY_CONSTRAINED: for.end: 401; LICM_ONLY_CONSTRAINED-NEXT: ret void 402; 403; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d_fast 404; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 405; LICM_AFTER_REASSOCIATE-NEXT: entry: 406; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_FMUL:%.*]] = fmul fast double [[D1]], [[DELTA]] 407; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_FMUL1:%.*]] = fmul fast double [[D2]], [[DELTA]] 408; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 409; LICM_AFTER_REASSOCIATE: for.cond: 410; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 411; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 412; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 413; LICM_AFTER_REASSOCIATE: for.body: 414; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 415; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 416; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 417; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 418; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[FACTOR_OP_FMUL]] 419; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 420; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 421; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 422; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[FACTOR_OP_FMUL1]] 423; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 424; LICM_AFTER_REASSOCIATE-NEXT: store double [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 425; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 426; LICM_AFTER_REASSOCIATE: for.end: 427; LICM_AFTER_REASSOCIATE-NEXT: ret void 428; 429; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d_fast 430; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 431; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 432; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 433; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 434; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 435; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 436; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 437; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 438; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 439; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 440; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 441; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 442; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 443; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 444; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 445; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 446; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[D2]] 447; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 448; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD]], [[DELTA]] 449; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 450; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 451; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 452; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 453; 454entry: 455 %fmul.d1 = fmul fast double %d1, %delta 456 %fmul.d2 = fmul fast double %d2, %delta 457 br label %for.cond 458 459for.cond: 460 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 461 %cmp.not = icmp sgt i32 %j, %i 462 br i1 %cmp.not, label %for.end, label %for.body 463 464for.body: 465 %add.j.1 = add nuw nsw i32 %j, 1 466 %idxprom.j.1 = zext i32 %add.j.1 to i64 467 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 468 %cell.1 = load double, ptr %arrayidx.j.1, align 8 469 %fmul.1 = fmul fast double %fmul.d1, %cell.1 470 %idxprom.j = zext i32 %j to i64 471 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 472 %cell.2 = load double, ptr %arrayidx.j, align 8 473 %fmul.2 = fmul fast double %fmul.d2, %cell.2 474 %fadd.1 = fadd fast double %fmul.1, %fmul.2 475 store double %fadd.1, ptr %arrayidx.j, align 8 476 br label %for.cond 477 478for.end: 479 ret void 480} 481 482; 483; The following loop will be modified by the 'Reassociate expressions' pass, 484; 485; int j; 486; const double d1d = d1 * delta; 487; const double d2d = d2 * delta; 488; const double d3d = d3 * delta; 489; 490; for (j = 0; j <= i; j++) 491; cells[j] = d1d * cells[j + 1] + d2d * cells[j] + d3d * cells[j + 2]; 492; 493; ...into this: 494; 495; int j; 496; 497; for (j = 0; j <= i; j++) 498; cells[j] = (d1 * cells[j + 1] + d2 * cells[j] + d3 * cells[j + 2]) * delta; 499; 500; We expect the LICM pass to undo this transformation. 501; 502 503 504define void @innermost_loop_3d_fast(i32 %i, double %d1, double %d2, double %d3, double %delta, ptr %cells) { 505; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_3d_fast 506; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[D3:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 507; REASSOCIATE_ONLY-NEXT: entry: 508; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 509; REASSOCIATE_ONLY: for.cond: 510; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 511; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 512; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 513; REASSOCIATE_ONLY: for.body: 514; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 515; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 516; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 517; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 518; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 519; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 520; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 521; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 522; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[D2]] 523; REASSOCIATE_ONLY-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 524; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 525; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 526; REASSOCIATE_ONLY-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 527; REASSOCIATE_ONLY-NEXT: [[FMUL_3:%.*]] = fmul fast double [[CELL_3]], [[D3]] 528; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 529; REASSOCIATE_ONLY-NEXT: [[REASS_ADD1:%.*]] = fadd fast double [[REASS_ADD]], [[FMUL_3]] 530; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD1]], [[DELTA]] 531; REASSOCIATE_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 532; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 533; REASSOCIATE_ONLY: for.end: 534; REASSOCIATE_ONLY-NEXT: ret void 535; 536; LICM_ONLY-LABEL: define void @innermost_loop_3d_fast 537; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[D3:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 538; LICM_ONLY-NEXT: entry: 539; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[D1]], [[DELTA]] 540; LICM_ONLY-NEXT: [[FMUL_D2:%.*]] = fmul fast double [[D2]], [[DELTA]] 541; LICM_ONLY-NEXT: [[FMUL_D3:%.*]] = fmul fast double [[D3]], [[DELTA]] 542; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 543; LICM_ONLY: for.cond: 544; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 545; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 546; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 547; LICM_ONLY: for.body: 548; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 549; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 550; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 551; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 552; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 553; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 554; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 555; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 556; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[FMUL_D2]], [[CELL_2]] 557; LICM_ONLY-NEXT: [[FADD_1:%.*]] = fadd fast double [[FMUL_1]], [[FMUL_2]] 558; LICM_ONLY-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 559; LICM_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 560; LICM_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 561; LICM_ONLY-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 562; LICM_ONLY-NEXT: [[FMUL_3:%.*]] = fmul fast double [[FMUL_D3]], [[CELL_3]] 563; LICM_ONLY-NEXT: [[FADD_2:%.*]] = fadd fast double [[FADD_1]], [[FMUL_3]] 564; LICM_ONLY-NEXT: store double [[FADD_2]], ptr [[ARRAYIDX_J_2]], align 8 565; LICM_ONLY-NEXT: br label [[FOR_COND]] 566; LICM_ONLY: for.end: 567; LICM_ONLY-NEXT: ret void 568; 569; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast 570; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[D3:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 571; LICM_ONLY_CONSTRAINED-NEXT: entry: 572; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = fmul fast double [[D1]], [[DELTA]] 573; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = fmul fast double [[D2]], [[DELTA]] 574; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D3:%.*]] = fmul fast double [[D3]], [[DELTA]] 575; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 576; LICM_ONLY_CONSTRAINED: for.cond: 577; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 578; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 579; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 580; LICM_ONLY_CONSTRAINED: for.body: 581; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 582; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 583; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 584; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 585; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[FMUL_D1]], [[CELL_1]] 586; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 587; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 588; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 589; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[FMUL_D2]], [[CELL_2]] 590; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_1:%.*]] = fadd fast double [[FMUL_1]], [[FMUL_2]] 591; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 592; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 593; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 594; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 595; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_3:%.*]] = fmul fast double [[FMUL_D3]], [[CELL_3]] 596; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_2:%.*]] = fadd fast double [[FADD_1]], [[FMUL_3]] 597; LICM_ONLY_CONSTRAINED-NEXT: store double [[FADD_2]], ptr [[ARRAYIDX_J_2]], align 8 598; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 599; LICM_ONLY_CONSTRAINED: for.end: 600; LICM_ONLY_CONSTRAINED-NEXT: ret void 601; 602; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_3d_fast 603; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[D3:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 604; LICM_AFTER_REASSOCIATE-NEXT: entry: 605; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_FMUL:%.*]] = fmul fast double [[D3]], [[DELTA]] 606; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_FMUL2:%.*]] = fmul fast double [[D1]], [[DELTA]] 607; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_FMUL3:%.*]] = fmul fast double [[D2]], [[DELTA]] 608; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 609; LICM_AFTER_REASSOCIATE: for.cond: 610; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 611; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 612; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 613; LICM_AFTER_REASSOCIATE: for.body: 614; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 615; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 616; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 617; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 618; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[FACTOR_OP_FMUL2]] 619; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 620; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 621; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 622; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[FACTOR_OP_FMUL3]] 623; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 624; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 625; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 626; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 627; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_3:%.*]] = fmul fast double [[CELL_3]], [[FACTOR_OP_FMUL]] 628; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 629; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD1:%.*]] = fadd fast double [[REASS_ADD]], [[FMUL_3]] 630; LICM_AFTER_REASSOCIATE-NEXT: store double [[REASS_ADD1]], ptr [[ARRAYIDX_J_2]], align 8 631; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 632; LICM_AFTER_REASSOCIATE: for.end: 633; LICM_AFTER_REASSOCIATE-NEXT: ret void 634; 635; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast 636; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[D3:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 637; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 638; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 639; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 640; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 641; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 642; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 643; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 644; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 645; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 646; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 647; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 648; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 649; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 650; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 651; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 652; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[D2]] 653; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 654; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 655; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 656; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 657; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_3:%.*]] = fmul fast double [[CELL_3]], [[D3]] 658; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 659; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = fadd fast double [[REASS_ADD]], [[FMUL_3]] 660; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD1]], [[DELTA]] 661; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 662; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 663; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 664; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 665; 666entry: 667 %fmul.d1 = fmul fast double %d1, %delta 668 %fmul.d2 = fmul fast double %d2, %delta 669 %fmul.d3 = fmul fast double %d3, %delta 670 br label %for.cond 671 672for.cond: 673 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 674 %cmp.not = icmp sgt i32 %j, %i 675 br i1 %cmp.not, label %for.end, label %for.body 676 677for.body: 678 %add.j.1 = add nuw nsw i32 %j, 1 679 %idxprom.j.1 = zext i32 %add.j.1 to i64 680 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 681 %cell.1 = load double, ptr %arrayidx.j.1, align 8 682 %fmul.1 = fmul fast double %fmul.d1, %cell.1 683 %idxprom.j = zext i32 %j to i64 684 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 685 %cell.2 = load double, ptr %arrayidx.j, align 8 686 %fmul.2 = fmul fast double %fmul.d2, %cell.2 687 %fadd.1 = fadd fast double %fmul.1, %fmul.2 688 %add.j.2 = add nuw nsw i32 %j, 2 689 %idxprom.j.2 = zext i32 %add.j.2 to i64 690 %arrayidx.j.2 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.2 691 %cell.3 = load double, ptr %arrayidx.j.2, align 8 692 %fmul.3 = fmul fast double %fmul.d3, %cell.3 693 %fadd.2 = fadd fast double %fadd.1, %fmul.3 694 store double %fadd.2, ptr %arrayidx.j.2, align 8 695 br label %for.cond 696 697for.end: 698 ret void 699} 700 701; 702; When there is no 'fast' attribute, the transformation should not happen. 703; 704 705define void @innermost_loop_2d_nofast(i32 %i, double %d1, double %d2, double %delta, ptr %cells) { 706; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d_nofast 707; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 708; REASSOCIATE_ONLY-NEXT: entry: 709; REASSOCIATE_ONLY-NEXT: [[FMUL_D1:%.*]] = fmul double [[D1]], [[DELTA]] 710; REASSOCIATE_ONLY-NEXT: [[FMUL_D2:%.*]] = fmul double [[D2]], [[DELTA]] 711; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 712; REASSOCIATE_ONLY: for.cond: 713; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 714; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 715; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 716; REASSOCIATE_ONLY: for.body: 717; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 718; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 719; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 720; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 721; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul double [[FMUL_D1]], [[CELL_1]] 722; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 723; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 724; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 725; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul double [[FMUL_D2]], [[CELL_2]] 726; REASSOCIATE_ONLY-NEXT: [[FADD_1:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 727; REASSOCIATE_ONLY-NEXT: store double [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 728; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 729; REASSOCIATE_ONLY: for.end: 730; REASSOCIATE_ONLY-NEXT: ret void 731; 732; LICM_ONLY-LABEL: define void @innermost_loop_2d_nofast 733; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 734; LICM_ONLY-NEXT: entry: 735; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = fmul double [[D1]], [[DELTA]] 736; LICM_ONLY-NEXT: [[FMUL_D2:%.*]] = fmul double [[D2]], [[DELTA]] 737; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 738; LICM_ONLY: for.cond: 739; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 740; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 741; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 742; LICM_ONLY: for.body: 743; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 744; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 745; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 746; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 747; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul double [[FMUL_D1]], [[CELL_1]] 748; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 749; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 750; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 751; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = fmul double [[FMUL_D2]], [[CELL_2]] 752; LICM_ONLY-NEXT: [[FADD_1:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 753; LICM_ONLY-NEXT: store double [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 754; LICM_ONLY-NEXT: br label [[FOR_COND]] 755; LICM_ONLY: for.end: 756; LICM_ONLY-NEXT: ret void 757; 758; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d_nofast 759; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 760; LICM_ONLY_CONSTRAINED-NEXT: entry: 761; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = fmul double [[D1]], [[DELTA]] 762; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = fmul double [[D2]], [[DELTA]] 763; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 764; LICM_ONLY_CONSTRAINED: for.cond: 765; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 766; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 767; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 768; LICM_ONLY_CONSTRAINED: for.body: 769; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 770; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 771; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 772; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 773; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul double [[FMUL_D1]], [[CELL_1]] 774; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 775; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 776; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 777; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul double [[FMUL_D2]], [[CELL_2]] 778; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_1:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 779; LICM_ONLY_CONSTRAINED-NEXT: store double [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 780; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 781; LICM_ONLY_CONSTRAINED: for.end: 782; LICM_ONLY_CONSTRAINED-NEXT: ret void 783; 784; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d_nofast 785; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 786; LICM_AFTER_REASSOCIATE-NEXT: entry: 787; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_D1:%.*]] = fmul double [[D1]], [[DELTA]] 788; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_D2:%.*]] = fmul double [[D2]], [[DELTA]] 789; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 790; LICM_AFTER_REASSOCIATE: for.cond: 791; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 792; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 793; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 794; LICM_AFTER_REASSOCIATE: for.body: 795; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 796; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 797; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 798; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 799; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul double [[FMUL_D1]], [[CELL_1]] 800; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 801; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 802; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 803; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul double [[FMUL_D2]], [[CELL_2]] 804; LICM_AFTER_REASSOCIATE-NEXT: [[FADD_1:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 805; LICM_AFTER_REASSOCIATE-NEXT: store double [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 806; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 807; LICM_AFTER_REASSOCIATE: for.end: 808; LICM_AFTER_REASSOCIATE-NEXT: ret void 809; 810; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d_nofast 811; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 812; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 813; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = fmul double [[D1]], [[DELTA]] 814; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = fmul double [[D2]], [[DELTA]] 815; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 816; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 817; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 818; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 819; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 820; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 821; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 822; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 823; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 824; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 825; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul double [[FMUL_D1]], [[CELL_1]] 826; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 827; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 828; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 829; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul double [[FMUL_D2]], [[CELL_2]] 830; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FADD_1:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 831; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 832; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 833; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 834; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 835; 836entry: 837 %fmul.d1 = fmul double %d1, %delta 838 %fmul.d2 = fmul double %d2, %delta 839 br label %for.cond 840 841for.cond: 842 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 843 %cmp.not = icmp sgt i32 %j, %i 844 br i1 %cmp.not, label %for.end, label %for.body 845 846for.body: 847 %add.j.1 = add nuw nsw i32 %j, 1 848 %idxprom.j.1 = zext i32 %add.j.1 to i64 849 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 850 %cell.1 = load double, ptr %arrayidx.j.1, align 8 851 %fmul.1 = fmul double %fmul.d1, %cell.1 852 %idxprom.j = zext i32 %j to i64 853 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 854 %cell.2 = load double, ptr %arrayidx.j, align 8 855 %fmul.2 = fmul double %fmul.d2, %cell.2 856 %fadd.1 = fadd double %fmul.1, %fmul.2 857 store double %fadd.1, ptr %arrayidx.j, align 8 858 br label %for.cond 859 860for.end: 861 ret void 862} 863 864; 865; The following loop should be modified by the LICM pass, 866; 867; int j; 868; 869; for (j = 0; j <= i; j++) 870; cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta; 871; 872; ...into this: 873; 874; int j; 875; const double d1d = d1 * delta; 876; const double d2d = d2 * delta; 877; 878; for (j = 0; j <= i; j++) 879; cells[j] = d1d * cells[j + 1] + d2d * cells[j]; 880; 881 882define void @innermost_loop_2d_fast_reassociated(i32 %i, double %d1, double %d2, double %delta, ptr %cells) { 883; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d_fast_reassociated 884; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 885; REASSOCIATE_ONLY-NEXT: entry: 886; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 887; REASSOCIATE_ONLY: for.cond: 888; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 889; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 890; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 891; REASSOCIATE_ONLY: for.body: 892; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 893; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 894; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 895; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 896; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 897; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 898; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 899; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 900; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[D2]] 901; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 902; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD]], [[DELTA]] 903; REASSOCIATE_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 904; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 905; REASSOCIATE_ONLY: for.end: 906; REASSOCIATE_ONLY-NEXT: ret void 907; 908; LICM_ONLY-LABEL: define void @innermost_loop_2d_fast_reassociated 909; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 910; LICM_ONLY-NEXT: entry: 911; LICM_ONLY-NEXT: [[FACTOR_OP_FMUL:%.*]] = fmul fast double [[D1]], [[DELTA]] 912; LICM_ONLY-NEXT: [[FACTOR_OP_FMUL1:%.*]] = fmul fast double [[D2]], [[DELTA]] 913; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 914; LICM_ONLY: for.cond: 915; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 916; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 917; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 918; LICM_ONLY: for.body: 919; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 920; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 921; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 922; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 923; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[FACTOR_OP_FMUL]] 924; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 925; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 926; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 927; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[FACTOR_OP_FMUL1]] 928; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 929; LICM_ONLY-NEXT: store double [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 930; LICM_ONLY-NEXT: br label [[FOR_COND]] 931; LICM_ONLY: for.end: 932; LICM_ONLY-NEXT: ret void 933; 934; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d_fast_reassociated 935; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 936; LICM_ONLY_CONSTRAINED-NEXT: entry: 937; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 938; LICM_ONLY_CONSTRAINED: for.cond: 939; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 940; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 941; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 942; LICM_ONLY_CONSTRAINED: for.body: 943; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 944; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 945; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 946; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 947; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 948; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 949; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 950; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 951; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[D2]] 952; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 953; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD]], [[DELTA]] 954; LICM_ONLY_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 955; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 956; LICM_ONLY_CONSTRAINED: for.end: 957; LICM_ONLY_CONSTRAINED-NEXT: ret void 958; 959; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d_fast_reassociated 960; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 961; LICM_AFTER_REASSOCIATE-NEXT: entry: 962; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_FMUL:%.*]] = fmul fast double [[D1]], [[DELTA]] 963; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_FMUL1:%.*]] = fmul fast double [[D2]], [[DELTA]] 964; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 965; LICM_AFTER_REASSOCIATE: for.cond: 966; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 967; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 968; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 969; LICM_AFTER_REASSOCIATE: for.body: 970; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 971; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 972; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 973; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 974; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[FACTOR_OP_FMUL]] 975; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 976; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 977; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 978; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[FACTOR_OP_FMUL1]] 979; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 980; LICM_AFTER_REASSOCIATE-NEXT: store double [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 981; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 982; LICM_AFTER_REASSOCIATE: for.end: 983; LICM_AFTER_REASSOCIATE-NEXT: ret void 984; 985; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d_fast_reassociated 986; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 987; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 988; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 989; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 990; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 991; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 992; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 993; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 994; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 995; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 996; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 997; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 998; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 999; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1000; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1001; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1002; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_2]], [[D2]] 1003; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 1004; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[REASS_ADD]], [[DELTA]] 1005; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1006; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 1007; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 1008; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 1009; 1010entry: 1011 br label %for.cond 1012 1013for.cond: 1014 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 1015 %cmp.not = icmp sgt i32 %j, %i 1016 br i1 %cmp.not, label %for.end, label %for.body 1017 1018for.body: 1019 %add.j.1 = add nuw nsw i32 %j, 1 1020 %idxprom.j.1 = zext i32 %add.j.1 to i64 1021 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 1022 %cell.1 = load double, ptr %arrayidx.j.1, align 8 1023 %fmul.1 = fmul fast double %cell.1, %d1 1024 %idxprom.j = zext i32 %j to i64 1025 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 1026 %cell.2 = load double, ptr %arrayidx.j, align 8 1027 %fmul.2 = fmul fast double %cell.2, %d2 1028 %reass.add = fadd fast double %fmul.2, %fmul.1 1029 %reass.mul = fmul fast double %reass.add, %delta 1030 store double %reass.mul, ptr %arrayidx.j, align 8 1031 br label %for.cond 1032 1033for.end: 1034 ret void 1035} 1036 1037; 1038; When there is no 'fast' attribute, the transformation should not happen. 1039; 1040 1041define void @innermost_loop_2d_nofast_reassociated(i32 %i, double %d1, double %d2, double %delta, ptr %cells) { 1042; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d_nofast_reassociated 1043; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1044; REASSOCIATE_ONLY-NEXT: entry: 1045; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 1046; REASSOCIATE_ONLY: for.cond: 1047; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1048; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1049; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1050; REASSOCIATE_ONLY: for.body: 1051; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1052; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1053; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1054; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1055; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul double [[D1]], [[CELL_1]] 1056; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1057; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1058; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1059; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul double [[D2]], [[CELL_2]] 1060; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 1061; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul double [[DELTA]], [[REASS_ADD]] 1062; REASSOCIATE_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1063; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 1064; REASSOCIATE_ONLY: for.end: 1065; REASSOCIATE_ONLY-NEXT: ret void 1066; 1067; LICM_ONLY-LABEL: define void @innermost_loop_2d_nofast_reassociated 1068; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1069; LICM_ONLY-NEXT: entry: 1070; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 1071; LICM_ONLY: for.cond: 1072; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1073; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1074; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1075; LICM_ONLY: for.body: 1076; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1077; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1078; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1079; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1080; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul double [[CELL_1]], [[D1]] 1081; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1082; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1083; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1084; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = fmul double [[CELL_2]], [[D2]] 1085; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd double [[FMUL_2]], [[FMUL_1]] 1086; LICM_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul double [[REASS_ADD]], [[DELTA]] 1087; LICM_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1088; LICM_ONLY-NEXT: br label [[FOR_COND]] 1089; LICM_ONLY: for.end: 1090; LICM_ONLY-NEXT: ret void 1091; 1092; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d_nofast_reassociated 1093; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1094; LICM_ONLY_CONSTRAINED-NEXT: entry: 1095; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 1096; LICM_ONLY_CONSTRAINED: for.cond: 1097; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1098; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1099; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1100; LICM_ONLY_CONSTRAINED: for.body: 1101; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1102; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1103; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1104; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1105; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul double [[CELL_1]], [[D1]] 1106; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1107; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1108; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1109; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul double [[CELL_2]], [[D2]] 1110; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd double [[FMUL_2]], [[FMUL_1]] 1111; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul double [[REASS_ADD]], [[DELTA]] 1112; LICM_ONLY_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1113; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 1114; LICM_ONLY_CONSTRAINED: for.end: 1115; LICM_ONLY_CONSTRAINED-NEXT: ret void 1116; 1117; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d_nofast_reassociated 1118; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1119; LICM_AFTER_REASSOCIATE-NEXT: entry: 1120; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 1121; LICM_AFTER_REASSOCIATE: for.cond: 1122; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1123; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1124; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1125; LICM_AFTER_REASSOCIATE: for.body: 1126; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1127; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1128; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1129; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1130; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul double [[D1]], [[CELL_1]] 1131; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1132; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1133; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1134; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul double [[D2]], [[CELL_2]] 1135; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 1136; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_MUL:%.*]] = fmul double [[DELTA]], [[REASS_ADD]] 1137; LICM_AFTER_REASSOCIATE-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1138; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 1139; LICM_AFTER_REASSOCIATE: for.end: 1140; LICM_AFTER_REASSOCIATE-NEXT: ret void 1141; 1142; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d_nofast_reassociated 1143; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1144; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 1145; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 1146; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 1147; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1148; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1149; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1150; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 1151; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1152; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1153; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1154; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1155; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul double [[D1]], [[CELL_1]] 1156; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1157; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1158; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1159; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul double [[D2]], [[CELL_2]] 1160; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd double [[FMUL_1]], [[FMUL_2]] 1161; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul double [[DELTA]], [[REASS_ADD]] 1162; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1163; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 1164; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 1165; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 1166; 1167entry: 1168 br label %for.cond 1169 1170for.cond: 1171 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 1172 %cmp.not = icmp sgt i32 %j, %i 1173 br i1 %cmp.not, label %for.end, label %for.body 1174 1175for.body: 1176 %add.j.1 = add nuw nsw i32 %j, 1 1177 %idxprom.j.1 = zext i32 %add.j.1 to i64 1178 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 1179 %cell.1 = load double, ptr %arrayidx.j.1, align 8 1180 %fmul.1 = fmul double %cell.1, %d1 1181 %idxprom.j = zext i32 %j to i64 1182 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 1183 %cell.2 = load double, ptr %arrayidx.j, align 8 1184 %fmul.2 = fmul double %cell.2, %d2 1185 %reass.add = fadd double %fmul.2, %fmul.1 1186 %reass.mul = fmul double %reass.add, %delta 1187 store double %reass.mul, ptr %arrayidx.j, align 8 1188 br label %for.cond 1189 1190for.end: 1191 ret void 1192} 1193; 1194; When there is no 'nsz' attribute, the transformation should not happen. 1195; 1196 1197define void @innermost_loop_2d_nonsz_reassociated(i32 %i, double %d1, double %d2, double %delta, ptr %cells) { 1198; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d_nonsz_reassociated 1199; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1200; REASSOCIATE_ONLY-NEXT: entry: 1201; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 1202; REASSOCIATE_ONLY: for.cond: 1203; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1204; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1205; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1206; REASSOCIATE_ONLY: for.body: 1207; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1208; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1209; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1210; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1211; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul reassoc double [[D1]], [[CELL_1]] 1212; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1213; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1214; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1215; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul reassoc double [[D2]], [[CELL_2]] 1216; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd reassoc double [[FMUL_1]], [[FMUL_2]] 1217; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul reassoc double [[DELTA]], [[REASS_ADD]] 1218; REASSOCIATE_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1219; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 1220; REASSOCIATE_ONLY: for.end: 1221; REASSOCIATE_ONLY-NEXT: ret void 1222; 1223; LICM_ONLY-LABEL: define void @innermost_loop_2d_nonsz_reassociated 1224; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1225; LICM_ONLY-NEXT: entry: 1226; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 1227; LICM_ONLY: for.cond: 1228; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1229; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1230; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1231; LICM_ONLY: for.body: 1232; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1233; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1234; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1235; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1236; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul reassoc double [[CELL_1]], [[D1]] 1237; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1238; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1239; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1240; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = fmul reassoc double [[CELL_2]], [[D2]] 1241; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd reassoc double [[FMUL_2]], [[FMUL_1]] 1242; LICM_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul reassoc double [[REASS_ADD]], [[DELTA]] 1243; LICM_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1244; LICM_ONLY-NEXT: br label [[FOR_COND]] 1245; LICM_ONLY: for.end: 1246; LICM_ONLY-NEXT: ret void 1247; 1248; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d_nonsz_reassociated 1249; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1250; LICM_ONLY_CONSTRAINED-NEXT: entry: 1251; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 1252; LICM_ONLY_CONSTRAINED: for.cond: 1253; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1254; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1255; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1256; LICM_ONLY_CONSTRAINED: for.body: 1257; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1258; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1259; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1260; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1261; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul reassoc double [[CELL_1]], [[D1]] 1262; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1263; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1264; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1265; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul reassoc double [[CELL_2]], [[D2]] 1266; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd reassoc double [[FMUL_2]], [[FMUL_1]] 1267; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul reassoc double [[REASS_ADD]], [[DELTA]] 1268; LICM_ONLY_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1269; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 1270; LICM_ONLY_CONSTRAINED: for.end: 1271; LICM_ONLY_CONSTRAINED-NEXT: ret void 1272; 1273; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d_nonsz_reassociated 1274; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1275; LICM_AFTER_REASSOCIATE-NEXT: entry: 1276; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 1277; LICM_AFTER_REASSOCIATE: for.cond: 1278; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1279; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1280; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1281; LICM_AFTER_REASSOCIATE: for.body: 1282; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1283; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1284; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1285; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1286; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul reassoc double [[D1]], [[CELL_1]] 1287; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1288; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1289; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1290; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul reassoc double [[D2]], [[CELL_2]] 1291; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = fadd reassoc double [[FMUL_1]], [[FMUL_2]] 1292; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_MUL:%.*]] = fmul reassoc double [[DELTA]], [[REASS_ADD]] 1293; LICM_AFTER_REASSOCIATE-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1294; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 1295; LICM_AFTER_REASSOCIATE: for.end: 1296; LICM_AFTER_REASSOCIATE-NEXT: ret void 1297; 1298; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d_nonsz_reassociated 1299; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1300; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 1301; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 1302; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 1303; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1304; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1305; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1306; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 1307; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1308; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1309; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1310; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1311; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul reassoc double [[D1]], [[CELL_1]] 1312; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1313; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1314; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1315; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul reassoc double [[D2]], [[CELL_2]] 1316; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd reassoc double [[FMUL_1]], [[FMUL_2]] 1317; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul reassoc double [[DELTA]], [[REASS_ADD]] 1318; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1319; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 1320; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 1321; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 1322; 1323entry: 1324 br label %for.cond 1325 1326for.cond: 1327 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 1328 %cmp.not = icmp sgt i32 %j, %i 1329 br i1 %cmp.not, label %for.end, label %for.body 1330 1331for.body: 1332 %add.j.1 = add nuw nsw i32 %j, 1 1333 %idxprom.j.1 = zext i32 %add.j.1 to i64 1334 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 1335 %cell.1 = load double, ptr %arrayidx.j.1, align 8 1336 %fmul.1 = fmul reassoc double %cell.1, %d1 1337 %idxprom.j = zext i32 %j to i64 1338 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 1339 %cell.2 = load double, ptr %arrayidx.j, align 8 1340 %fmul.2 = fmul reassoc double %cell.2, %d2 1341 %reass.add = fadd reassoc double %fmul.2, %fmul.1 1342 %reass.mul = fmul reassoc double %reass.add, %delta 1343 store double %reass.mul, ptr %arrayidx.j, align 8 1344 br label %for.cond 1345 1346for.end: 1347 ret void 1348} 1349 1350; 1351; The following loop will not be modified by the LICM pass: 1352; 1353; int j; 1354; 1355; for (j = 0; j <= i; j++) 1356; cells[j] = (d1 * cells[j + 1] + d2 * cells[j] + 1357; cells[j] * cells[j + 1]) * delta; 1358; 1359; This case differs as one of the multiplications involves no invariants. 1360; 1361 1362define void @innermost_loop_3d_fast_reassociated_different(i32 %i, double %d1, double %d2, double %delta, ptr %cells) { 1363; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_3d_fast_reassociated_different 1364; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1365; REASSOCIATE_ONLY-NEXT: entry: 1366; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] 1367; REASSOCIATE_ONLY: for.cond: 1368; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1369; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1370; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1371; REASSOCIATE_ONLY: for.body: 1372; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1373; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1374; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1375; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1376; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 1377; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 1378; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1379; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_3:%.*]] = zext i32 [[ADD_J_1]] to i64 1380; REASSOCIATE_ONLY-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1381; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1382; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1383; REASSOCIATE_ONLY-NEXT: [[CELL_4:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1384; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 1385; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_4]], [[D2]] 1386; REASSOCIATE_ONLY-NEXT: [[EXTRA_MUL:%.*]] = fmul fast double [[CELL_3]], [[CELL_2]] 1387; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[EXTRA_MUL]], [[FMUL_1]] 1388; REASSOCIATE_ONLY-NEXT: [[EXTRA_ADD:%.*]] = fadd fast double [[REASS_ADD]], [[FMUL_2]] 1389; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[EXTRA_ADD]], [[DELTA]] 1390; REASSOCIATE_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1391; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] 1392; REASSOCIATE_ONLY: for.end: 1393; REASSOCIATE_ONLY-NEXT: ret void 1394; 1395; LICM_ONLY-LABEL: define void @innermost_loop_3d_fast_reassociated_different 1396; LICM_ONLY-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1397; LICM_ONLY-NEXT: entry: 1398; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] 1399; LICM_ONLY: for.cond: 1400; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1401; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1402; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1403; LICM_ONLY: for.body: 1404; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1405; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1406; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1407; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1408; LICM_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 1409; LICM_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 1410; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1411; LICM_ONLY-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1412; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1413; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1414; LICM_ONLY-NEXT: [[CELL_4:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1415; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 1416; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_4]], [[D2]] 1417; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 1418; LICM_ONLY-NEXT: [[EXTRA_MUL:%.*]] = fmul fast double [[CELL_3]], [[CELL_2]] 1419; LICM_ONLY-NEXT: [[EXTRA_ADD:%.*]] = fadd fast double [[EXTRA_MUL]], [[REASS_ADD]] 1420; LICM_ONLY-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[EXTRA_ADD]], [[DELTA]] 1421; LICM_ONLY-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1422; LICM_ONLY-NEXT: br label [[FOR_COND]] 1423; LICM_ONLY: for.end: 1424; LICM_ONLY-NEXT: ret void 1425; 1426; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast_reassociated_different 1427; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1428; LICM_ONLY_CONSTRAINED-NEXT: entry: 1429; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 1430; LICM_ONLY_CONSTRAINED: for.cond: 1431; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1432; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1433; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1434; LICM_ONLY_CONSTRAINED: for.body: 1435; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1436; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1437; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1438; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1439; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 1440; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 1441; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1442; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1443; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1444; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1445; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_4:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1446; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 1447; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_4]], [[D2]] 1448; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[FMUL_2]], [[FMUL_1]] 1449; LICM_ONLY_CONSTRAINED-NEXT: [[EXTRA_MUL:%.*]] = fmul fast double [[CELL_3]], [[CELL_2]] 1450; LICM_ONLY_CONSTRAINED-NEXT: [[EXTRA_ADD:%.*]] = fadd fast double [[EXTRA_MUL]], [[REASS_ADD]] 1451; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[EXTRA_ADD]], [[DELTA]] 1452; LICM_ONLY_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1453; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] 1454; LICM_ONLY_CONSTRAINED: for.end: 1455; LICM_ONLY_CONSTRAINED-NEXT: ret void 1456; 1457; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_3d_fast_reassociated_different 1458; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1459; LICM_AFTER_REASSOCIATE-NEXT: entry: 1460; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] 1461; LICM_AFTER_REASSOCIATE: for.cond: 1462; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1463; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1464; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1465; LICM_AFTER_REASSOCIATE: for.body: 1466; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1467; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1468; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1469; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1470; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 1471; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 1472; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1473; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1474; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1475; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1476; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_4:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1477; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 1478; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_4]], [[D2]] 1479; LICM_AFTER_REASSOCIATE-NEXT: [[EXTRA_MUL:%.*]] = fmul fast double [[CELL_3]], [[CELL_2]] 1480; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[EXTRA_MUL]], [[FMUL_1]] 1481; LICM_AFTER_REASSOCIATE-NEXT: [[EXTRA_ADD:%.*]] = fadd fast double [[REASS_ADD]], [[FMUL_2]] 1482; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[EXTRA_ADD]], [[DELTA]] 1483; LICM_AFTER_REASSOCIATE-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1484; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] 1485; LICM_AFTER_REASSOCIATE: for.end: 1486; LICM_AFTER_REASSOCIATE-NEXT: ret void 1487; 1488; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast_reassociated_different 1489; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], double [[D1:%.*]], double [[D2:%.*]], double [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 1490; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: 1491; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 1492; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: 1493; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 1494; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 1495; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 1496; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: 1497; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 1498; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 1499; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 1500; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load double, ptr [[ARRAYIDX_J_1]], align 8 1501; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 1502; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 1503; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1504; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load double, ptr [[ARRAYIDX_J_2]], align 8 1505; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 1506; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds double, ptr [[CELLS]], i64 [[IDXPROM_J]] 1507; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_4:%.*]] = load double, ptr [[ARRAYIDX_J]], align 8 1508; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = fmul fast double [[CELL_1]], [[D1]] 1509; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = fmul fast double [[CELL_4]], [[D2]] 1510; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[EXTRA_MUL:%.*]] = fmul fast double [[CELL_3]], [[CELL_2]] 1511; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = fadd fast double [[EXTRA_MUL]], [[FMUL_1]] 1512; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[EXTRA_ADD:%.*]] = fadd fast double [[REASS_ADD]], [[FMUL_2]] 1513; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = fmul fast double [[EXTRA_ADD]], [[DELTA]] 1514; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store double [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 1515; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] 1516; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: 1517; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void 1518; 1519entry: 1520 br label %for.cond 1521 1522for.cond: 1523 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 1524 %cmp.not = icmp sgt i32 %j, %i 1525 br i1 %cmp.not, label %for.end, label %for.body 1526 1527for.body: 1528 %add.j.1 = add nuw nsw i32 %j, 1 1529 %idxprom.j.1 = zext i32 %add.j.1 to i64 1530 %arrayidx.j.1 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.1 1531 %cell.1 = load double, ptr %arrayidx.j.1, align 8 1532 %add.j.2 = add nuw nsw i32 %j, 2 1533 %idxprom.j.2 = zext i32 %add.j.1 to i64 1534 %arrayidx.j.2 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.2 1535 %cell.2 = load double, ptr %arrayidx.j.2, align 8 1536 %add.j.3 = add nuw nsw i32 %j, 3 1537 %idxprom.j.3 = zext i32 %add.j.1 to i64 1538 %arrayidx.j.3 = getelementptr inbounds double, ptr %cells, i64 %idxprom.j.3 1539 %cell.3 = load double, ptr %arrayidx.j.2, align 8 1540 %idxprom.j = zext i32 %j to i64 1541 %arrayidx.j = getelementptr inbounds double, ptr %cells, i64 %idxprom.j 1542 %cell.4 = load double, ptr %arrayidx.j, align 8 1543 %fmul.1 = fmul fast double %cell.1, %d1 1544 %fmul.2 = fmul fast double %cell.4, %d2 1545 %reass.add = fadd fast double %fmul.2, %fmul.1 1546 %extra.mul = fmul fast double %cell.3, %cell.2 1547 %extra.add = fadd fast double %extra.mul, %reass.add 1548 %reass.mul = fmul fast double %extra.add, %delta 1549 store double %reass.mul, ptr %arrayidx.j, align 8 1550 br label %for.cond 1551 1552for.end: 1553 ret void 1554} 1555