@@ -461,6 +461,11 @@ void PeepholeTypeLegalizer::legalizeBinaryOperator(Instruction& I) {
461
461
NewLargeRes = m_builder->CreateAShr (NewLargeSrc1, NewLargeSrc2);
462
462
break ;
463
463
}
464
+ case Instruction::Shl:
465
+ {
466
+ NewLargeRes = m_builder->CreateShl (NewLargeSrc1, NewLargeSrc2);
467
+ break ;
468
+ }
464
469
default :
465
470
printf (" Binary Instruction seen with illegal int type. Legalization support missing. Inst opcode:%d" , I.getOpcode ());
466
471
IGC_ASSERT_MESSAGE (0 , " Binary Instruction seen with illegal int type. Legalization support missing." );
@@ -895,20 +900,59 @@ void PeepholeTypeLegalizer::cleanupTruncInst(Instruction& I) {
895
900
I.hasOneUse () &&
896
901
isLegalInteger (I.getOperand (0 )->getType ()->getScalarSizeInBits ()))
897
902
{
898
- // Need to see if it is safe to wipe it out. It is safe only if the user is a
899
- // SExt or ZExt and the trunc starting bitwidth is less than the
900
- // users bitwidth.
903
+ // Need to see if it is safe to replace, combine, or wipe out
901
904
Value* new_inst = NULL ;
902
905
Instruction* castInst = I.user_back ();
903
906
auto Src = I.getOperand (0 );
904
907
auto Src_bitsize = Src->getType ()->getScalarSizeInBits ();
908
+ auto Trunc_bitsize = I.getType ()->getScalarSizeInBits ();
905
909
auto castInst_bitsize = castInst->getType ()->getScalarSizeInBits ();
906
- if (Src_bitsize < castInst_bitsize)
910
+ if (Src_bitsize <= castInst_bitsize)
907
911
{
912
+ // Example 1:
913
+ // %a = trunc i8 %in to i5
914
+ // %out = sext i5 %a to i32
915
+ // =>
916
+ // %q = zext i8 %in to i32
917
+ // %s = shl i32 %q, 27
918
+ // %out = ashr i32 %s, 27
919
+
920
+ // Example 2:
921
+ // %a = trunc i8 %in to i5
922
+ // %out = zext i5 %a to i32
923
+ // =>
924
+ // %q = and i8 %in, 31
925
+ // %out = zext i8 %q to i32
926
+
908
927
if (isa<SExtInst>(castInst))
909
- new_inst = m_builder->CreateSExt (Src, castInst->getType ());
910
- if (isa<ZExtInst>(castInst))
911
- new_inst = m_builder->CreateZExt (Src, castInst->getType ());
928
+ {
929
+ auto shiftAmt = castInst_bitsize - Trunc_bitsize;
930
+ auto inst1 = m_builder->CreateZExt (Src, castInst->getType ());
931
+ auto inst2 = m_builder->CreateShl (inst1, shiftAmt);
932
+ new_inst = m_builder->CreateAShr (inst2, shiftAmt);
933
+ }
934
+ else if (isa<ZExtInst>(castInst))
935
+ {
936
+ auto inst1 = m_builder->CreateAnd (Src, (1 << Trunc_bitsize) - 1 );
937
+ new_inst = m_builder->CreateZExt (inst1, castInst->getType ());
938
+ }
939
+ }
940
+ else if (Src_bitsize > castInst_bitsize)
941
+ {
942
+ // Most likely a trunc instruction lets combine these two truncs and try again
943
+ // Example:
944
+ // %261 = trunc i8 %260 to i5
945
+ // %262 = trunc i5 %261 to i3
946
+ // ------>
947
+ // %out = trunc i8 %260 to i3
948
+ if (isa<TruncInst>(castInst))
949
+ {
950
+ auto new_val = m_builder->CreateTrunc (Src, castInst->getType ());
951
+ castInst->replaceAllUsesWith (new_val);
952
+ if (auto *new_trunc = dyn_cast<TruncInst>(new_val))
953
+ cleanupTruncInst (*new_trunc);
954
+ Changed = true ;
955
+ }
912
956
}
913
957
914
958
if (new_inst != NULL )
0 commit comments