@@ -372,10 +372,36 @@ void SymbolicEvaluation::getSymExprOrConstant(const Value* V, SymExpr*& S, int64
372
372
373
373
if (const ConstantInt * CI = dyn_cast<const ConstantInt>(V))
374
374
{
375
+ // symExpr handles symbols with the same bit size, thus sext/zext/trunc
376
+ // are not handled. With this, a result from either signed or unsigned
377
+ // integer operations will end up with the same bit pattern. Here, we
378
+ // choose to use sext on constants.
375
379
C = CI->getSExtValue ();
376
380
return ;
377
381
}
378
382
383
+ // Used for nomalizing shift amount.
384
+ // For example, i64, its type mask is 03F(63 = 64 - 1).
385
+ auto getTypeMask = [](const Type* Ty) -> uint32_t {
386
+ // For simplicity, only handle type whose size is power of 2.
387
+ uint32_t nbits = Ty->getScalarSizeInBits ();
388
+ if (nbits > 0 && isPowerOf2_32 (nbits))
389
+ return (nbits - 1 );
390
+ return 0 ;
391
+ };
392
+
393
+ // Return value:
394
+ // Shift amount: if it is valid and greater than 0
395
+ // 0 : invalid
396
+ auto getShlAmt = [&getTypeMask](const Instruction* ShlInst) -> uint32_t {
397
+ IGC_ASSERT (ShlInst->getOpcode () == Instruction::Shl);
398
+ uint32_t shtAmtMask = getTypeMask (ShlInst->getType ());
399
+ ConstantInt* cI = cast<ConstantInt>(ShlInst->getOperand (1 ));
400
+ if (cI && shtAmtMask > 0 )
401
+ return (uint32_t )(cI->getZExtValue () & shtAmtMask);
402
+ return 0 ;
403
+ };
404
+
379
405
// Instructions/Operators handled for now:
380
406
// GEP
381
407
// bitcast (inttoptr, ptrtoint, etc)
@@ -515,6 +541,35 @@ void SymbolicEvaluation::getSymExprOrConstant(const Value* V, SymExpr*& S, int64
515
541
}
516
542
break ;
517
543
}
544
+ case Instruction::Or:
545
+ {
546
+ // Check if it is actually an add.
547
+ //
548
+ // %mul = shl nuw nsw i64 %v, 1
549
+ // %add = or i64 %mul, 1
550
+ // --> %add = add %mul, 1
551
+ const Value* V0 = Op->getOperand (0 );
552
+ const Value* V1 = Op->getOperand (1 );
553
+ getSymExprOrConstant (V0, S0, C0);
554
+ getSymExprOrConstant (V1, S1, C1);
555
+ if (!S0 && !S1) {
556
+ C = C0 | C1;
557
+ return ;
558
+ }
559
+
560
+ // Case: 'or V0 Const' or 'or const V1'
561
+ if ((S0 && !S1) || (!S0 && S1)) {
562
+ const Value* tV = (S0 ? V0 : V1);
563
+ const uint64_t tC = (uint64_t )(S0 ? C1 : C0);
564
+ const Instruction* tI = dyn_cast<Instruction>(tV);
565
+ if (tI && tI->getOpcode () == Instruction::Shl) {
566
+ uint32_t shtAmt = getShlAmt (tI);
567
+ if (shtAmt > 0 && (1ull << shtAmt) > tC)
568
+ S = add (S0 ? S0 : S1, tC);
569
+ }
570
+ }
571
+ break ;
572
+ }
518
573
case Instruction::Mul:
519
574
{
520
575
const Value* V0 = Op->getOperand (0 );
@@ -538,7 +593,34 @@ void SymbolicEvaluation::getSymExprOrConstant(const Value* V, SymExpr*& S, int64
538
593
539
594
break ;
540
595
}
596
+ case Instruction::Shl:
597
+ {
598
+ // shl is a mul
599
+ // shl a, b, 2
600
+ // -> mul a, b, (1 << 2)
601
+ const Value* V0 = Op->getOperand (0 );
602
+ const Value* V1 = Op->getOperand (1 );
603
+ getSymExprOrConstant (V0, S0, C0);
604
+ getSymExprOrConstant (V1, S1, C1);
605
+
606
+ uint32_t shtAmtMask = getTypeMask (V->getType ());
607
+ if (shtAmtMask == 0 ) // sanity
608
+ break ;
541
609
610
+ if (!S1) {
611
+ C1 = (C1 & shtAmtMask);
612
+ }
613
+
614
+ if (!S0 && !S1) {
615
+ C = (C0 << C1);
616
+ return ;
617
+ }
618
+ if (!S1) {
619
+ uint64_t tC = (1ull << C1);
620
+ S = mul (S0, tC);
621
+ }
622
+ break ;
623
+ }
542
624
case Instruction::BitCast:
543
625
case Instruction::IntToPtr:
544
626
case Instruction::PtrToInt:
0 commit comments