@@ -1432,16 +1432,64 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds,
1432
1432
if (GEP->getInRange ())
1433
1433
return nullptr ;
1434
1434
1435
- // Only handle simple case with leading zero index. We cannot perform an
1436
- // actual addition as we don't know the correct index type size to use.
1437
1435
Constant *Idx0 = cast<Constant>(Idxs[0 ]);
1438
- if (!Idx0->isNullValue ())
1436
+ if (Idx0->isNullValue ()) {
1437
+ // Handle the simple case of a zero index.
1438
+ SmallVector<Value*, 16 > NewIndices;
1439
+ NewIndices.reserve (Idxs.size () + GEP->getNumIndices ());
1440
+ NewIndices.append (GEP->idx_begin (), GEP->idx_end ());
1441
+ NewIndices.append (Idxs.begin () + 1 , Idxs.end ());
1442
+ return ConstantExpr::getGetElementPtr (
1443
+ GEP->getSourceElementType (), cast<Constant>(GEP->getPointerOperand ()),
1444
+ NewIndices, InBounds && GEP->isInBounds ());
1445
+ }
1446
+
1447
+ gep_type_iterator LastI = gep_type_end (GEP);
1448
+ for (gep_type_iterator I = gep_type_begin (GEP), E = gep_type_end (GEP);
1449
+ I != E; ++I)
1450
+ LastI = I;
1451
+
1452
+ // We can't combine GEPs if the last index is a struct type.
1453
+ if (!LastI.isSequential ())
1454
+ return nullptr ;
1455
+ // We could perform the transform with non-constant index, but prefer leaving
1456
+ // it as GEP of GEP rather than GEP of add for now.
1457
+ ConstantInt *CI = dyn_cast<ConstantInt>(Idx0);
1458
+ if (!CI)
1459
+ return nullptr ;
1460
+
1461
+ // TODO: This code may be extended to handle vectors as well.
1462
+ auto *LastIdx = cast<Constant>(GEP->getOperand (GEP->getNumOperands ()-1 ));
1463
+ Type *LastIdxTy = LastIdx->getType ();
1464
+ if (LastIdxTy->isVectorTy ())
1439
1465
return nullptr ;
1440
1466
1441
1467
SmallVector<Value*, 16 > NewIndices;
1442
1468
NewIndices.reserve (Idxs.size () + GEP->getNumIndices ());
1443
- NewIndices.append (GEP->idx_begin (), GEP->idx_end ());
1469
+ NewIndices.append (GEP->idx_begin (), GEP->idx_end () - 1 );
1470
+
1471
+ // Add the last index of the source with the first index of the new GEP.
1472
+ // Make sure to handle the case when they are actually different types.
1473
+ if (LastIdxTy != Idx0->getType ()) {
1474
+ unsigned CommonExtendedWidth =
1475
+ std::max (LastIdxTy->getIntegerBitWidth (),
1476
+ Idx0->getType ()->getIntegerBitWidth ());
1477
+ CommonExtendedWidth = std::max (CommonExtendedWidth, 64U );
1478
+
1479
+ Type *CommonTy =
1480
+ Type::getIntNTy (LastIdxTy->getContext (), CommonExtendedWidth);
1481
+ if (Idx0->getType () != CommonTy)
1482
+ Idx0 = ConstantFoldCastInstruction (Instruction::SExt, Idx0, CommonTy);
1483
+ if (LastIdx->getType () != CommonTy)
1484
+ LastIdx =
1485
+ ConstantFoldCastInstruction (Instruction::SExt, LastIdx, CommonTy);
1486
+ if (!Idx0 || !LastIdx)
1487
+ return nullptr ;
1488
+ }
1489
+
1490
+ NewIndices.push_back (ConstantExpr::get (Instruction::Add, Idx0, LastIdx));
1444
1491
NewIndices.append (Idxs.begin () + 1 , Idxs.end ());
1492
+
1445
1493
return ConstantExpr::getGetElementPtr (
1446
1494
GEP->getSourceElementType (), cast<Constant>(GEP->getPointerOperand ()),
1447
1495
NewIndices, InBounds && GEP->isInBounds ());
0 commit comments