diff options
author | Michelle McDaniel <adiaaida@gmail.com> | 2016-09-09 10:44:03 -0700 |
---|---|---|
committer | Michelle McDaniel <adiaaida@gmail.com> | 2016-09-16 13:08:29 -0700 |
commit | 5c5e53363fd7ae7228764a006de1b1f158e64a16 (patch) | |
tree | 8320293693383101ff3517f746dec39c4130f615 /src/jit/gtlist.h | |
parent | 832a7498bf7aff89a70800c5f02517866f93dc1f (diff) | |
download | coreclr-5c5e53363fd7ae7228764a006de1b1f158e64a16.tar.gz coreclr-5c5e53363fd7ae7228764a006de1b1f158e64a16.tar.bz2 coreclr-5c5e53363fd7ae7228764a006de1b1f158e64a16.zip |
Add optimization for shift by CNS_INT
This change adds support for shifting by a GT_CNS_INT without going
through a helper. If the shiftOp is a GT_CNS_INT we do several
transformations based on the shift amount:
If the shift amount is 0, the shift is a nop, so we just put together the
hi and lo ops as a GT_LONG.
If the shift amount is < 32, we generate a shl/shld pattern, a shr/shrd
pattern or a sar/shrd pattern, depending on the oper. The first operand of
the shrd/shld is a GT_LONG, which we crack in codegen, using it
essentially as two int operands, rather than creating a tri op GenTree
node (essentially so that we can have 3 operands, instead of the normal
two).
If the shift amount is 32, it differs between shifting left and shifting
right. For GT_LSH, we move the loOp into the hiResult and set the loResult
to 0. For GT_RSZ, we move the hiOp into the loResult, and set the hiResult
to 0. For GT_RSH, we move the hiOp into the loResult, and set the hiResult
to a 31 bit signed shift of the hiOp to sign extend.
If the shift amount is less than 64, but larger than 32: for GT_LSH, the
hiResult is a shift of the loOp by shift amount - 32 (the move from lo into hi is
the 32 bit shift). We set the loResult to 0. For GT_RSH and GT_RSZ, the
loResult is a right shift (signed for GT_RSH) of the hiOp by shift amount
- 32. The hiResult is 0 for GT_RSZ, and a 31 bit signed shift of hiOp1 for
GT_RSH.
If the shift amount is >= 64, we set both hiResult and loResult to 0 for
GT_LSH and GT_RSZ, and do a sign extend shift to set hiResult and loResult
to the sign of the original hiOp for GT_RSH.
Diffstat (limited to 'src/jit/gtlist.h')
-rw-r--r-- | src/jit/gtlist.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/src/jit/gtlist.h b/src/jit/gtlist.h index bc2f8f2457..3bf360355b 100644 --- a/src/jit/gtlist.h +++ b/src/jit/gtlist.h @@ -179,6 +179,16 @@ GTNODE(MUL_LONG , "*long" ,GenTreeOp ,1,GTK_BINOP) // A // helper calls. It is similar to GT_MULHI, the difference being that // GT_MULHI drops the lo part of the result, whereas GT_MUL_LONG keeps // both parts of the result. + +// The following are nodes that specify shifts that take a GT_LONG op1. The GT_LONG +// contains the hi and lo parts of three operand shift form where one op will be +// shifted into the other op as part of the operation (LSH_HI will shift +// the high bits of the lo operand into the high operand as it shifts left. RSH_LO +// will shift the lo bits of the high operand into the lo operand). LSH_HI +// represents the high operation of a 64-bit left shift by a constant int, and +// RSH_LO represents the lo operation of a 64-bit right shift by a constant int. +GTNODE(LSH_HI , "<<Hi" ,GenTreeOp ,0,GTK_BINOP) +GTNODE(RSH_LO , ">>Lo" ,GenTreeOp ,0,GTK_BINOP) #endif // !defined(LEGACY_BACKEND) && !defined(_TARGET_64BIT_) #ifdef FEATURE_SIMD |