newCTFE Status July 2017

Stefan Koch via Digitalmars-d digitalmars-d at puremagic.com
Fri Jul 28 09:22:58 PDT 2017


On Thursday, 13 July 2017 at 12:45:19 UTC, Stefan Koch wrote:
> [ ... ]
Hi Guys I just fixed another bug that had me puzzled for a while.

The following function

ulong swap(ulong val)
{
     ulong result;

         result |= (val & 0xFF) << 56;
         result |= (val & 0xFF00) << 40;
         result |= (val & 0xFF00_00) << 24;
         result |= (val & 0xFF00_0000) << 8;

         result |= (val & 0xFF00_0000_00) >> 8;
         result |= (val & 0xFF00_0000_0000) >> 24;
         result |= (val & 0xFF00_0000_0000_00) >> 40;
         result |= (val & 0xFF00_0000_0000_0000) >> 56;

     return result;
}

would return strange values.
pragma(msg, swap(0xABCD_EF01_2345_6789)); // returns  
9900958322423496704
                                           // expected 
9900958322455989675
On further inspection the actual return value has only zeros in 
the lower 32 bits.

The generated IR however looks completey correct.

     Initialize();
         Line(1);

         auto val_1 = genParameter(BCType(BCTypeEnum.i64));//SP[4]
         beginFunction(0);//swap
             Line(2);
             Line(3);
             auto result_1 = genLocal(BCType(BCTypeEnum.i64), 
"result");//SP[8]
             Set(result_1, BCValue(Imm64(0)));
             Line(5);
             auto tmp1 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[16]
             auto tmp2 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[24]
             And3(tmp2, val_1, BCValue(Imm64(255)));
             auto tmp3 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[32]
             Le3(tmp3, BCValue(Imm32(56)), BCValue(Imm32(63)));
             auto tmp4 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[36]
             Set(tmp4, BCValue(Imm32(56)));
             auto tmp5 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[40]
             Set(tmp5, BCValue(Imm32(63)));
             Assert(tmp3, Imm32(1) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(56)), BCValue(Imm32(63))*/;);
             Lsh3(tmp1, tmp2, BCValue(Imm32(56)));
             Or3(result_1, result_1, tmp1);
             Line(6);
             auto tmp6 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[44]
             auto tmp7 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[52]
             And3(tmp7, val_1, BCValue(Imm64(65280)));
             auto tmp8 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[60]
             Le3(tmp8, BCValue(Imm32(40)), BCValue(Imm32(63)));
             auto tmp9 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[64]
             Set(tmp9, BCValue(Imm32(40)));
             auto tmp10 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[68]
             Set(tmp10, BCValue(Imm32(63)));
             Assert(tmp8, Imm32(2) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(40)), BCValue(Imm32(63))*/;);
             Lsh3(tmp6, tmp7, BCValue(Imm32(40)));
             Or3(result_1, result_1, tmp6);
             Line(7);
             auto tmp11 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[72]
             auto tmp12 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[80]
             And3(tmp12, val_1, BCValue(Imm64(16711680)));
             auto tmp13 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[88]
             Le3(tmp13, BCValue(Imm32(24)), BCValue(Imm32(63)));
             auto tmp14 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[92]
             Set(tmp14, BCValue(Imm32(24)));
             auto tmp15 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[96]
             Set(tmp15, BCValue(Imm32(63)));
             Assert(tmp13, Imm32(3) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(24)), BCValue(Imm32(63))*/;);
             Lsh3(tmp11, tmp12, BCValue(Imm32(24)));
             Or3(result_1, result_1, tmp11);
             Line(8);
             auto tmp16 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[100]
             auto tmp17 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[108]
             And3(tmp17, val_1, BCValue(Imm64(4278190080)));
             auto tmp18 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[116]
             Le3(tmp18, BCValue(Imm32(8)), BCValue(Imm32(63)));
             auto tmp19 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[120]
             Set(tmp19, BCValue(Imm32(8)));
             auto tmp20 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[124]
             Set(tmp20, BCValue(Imm32(63)));
             Assert(tmp18, Imm32(4) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(8)), BCValue(Imm32(63))*/;);
             Lsh3(tmp16, tmp17, BCValue(Imm32(8)));
             Or3(result_1, result_1, tmp16);
             Line(10);
             auto tmp21 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[128]
             auto tmp22 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[136]
             And3(tmp22, val_1, BCValue(Imm64(1095216660480)));
             auto tmp23 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[144]
             Le3(tmp23, BCValue(Imm32(8)), BCValue(Imm32(63)));
             auto tmp24 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[148]
             Set(tmp24, BCValue(Imm32(8)));
             auto tmp25 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[152]
             Set(tmp25, BCValue(Imm32(63)));
             Assert(tmp23, Imm32(5) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(8)), BCValue(Imm32(63))*/;);
             Rsh3(tmp21, tmp22, BCValue(Imm32(8)));
             Or3(result_1, result_1, tmp21);
             Line(11);
             auto tmp26 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[156]
             auto tmp27 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[164]
             And3(tmp27, val_1, BCValue(Imm64(280375465082880)));
             auto tmp28 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[172]
             Le3(tmp28, BCValue(Imm32(24)), BCValue(Imm32(63)));
             auto tmp29 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[176]
             Set(tmp29, BCValue(Imm32(24)));
             auto tmp30 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[180]
             Set(tmp30, BCValue(Imm32(63)));
             Assert(tmp28, Imm32(6) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(24)), BCValue(Imm32(63))*/;);
             Rsh3(tmp26, tmp27, BCValue(Imm32(24)));
             Or3(result_1, result_1, tmp26);
             Line(12);
             auto tmp31 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[184]
             auto tmp32 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[192]
             And3(tmp32, val_1, BCValue(Imm64(71776119061217280)));
             auto tmp33 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[200]
             Le3(tmp33, BCValue(Imm32(40)), BCValue(Imm32(63)));
             auto tmp34 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[204]
             Set(tmp34, BCValue(Imm32(40)));
             auto tmp35 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[208]
             Set(tmp35, BCValue(Imm32(63)));
             Assert(tmp33, Imm32(7) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(40)), BCValue(Imm32(63))*/;);
             Rsh3(tmp31, tmp32, BCValue(Imm32(40)));
             Or3(result_1, result_1, tmp31);
             Line(13);
             auto tmp36 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[212]
             auto tmp37 = 
genTemporary(BCType(BCTypeEnum.i64));//SP[220]
             And3(tmp37, val_1, 
BCValue(Imm64(18374686479671623680)));
             auto tmp38 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[228]
             Le3(tmp38, BCValue(Imm32(56)), BCValue(Imm32(63)));
             auto tmp39 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[232]
             Set(tmp39, BCValue(Imm32(56)));
             auto tmp40 = 
genTemporary(BCType(BCTypeEnum.i32));//SP[236]
             Set(tmp40, BCValue(Imm32(63)));
             Assert(tmp38, Imm32(8) /*"shift by %d is outside the 
range 0..%d", BCValue(Imm32(56)), BCValue(Imm32(63))*/;);
             Rsh3(tmp36, tmp37, BCValue(Imm32(56)));
             Or3(result_1, result_1, tmp36);
             Line(26);
             Ret(result_1);
             Line(27);
         endFunction();

         Line(28);
     Finalize();

So what is going wrong here ?

The 4 lines responsible for the lower 32bit of the result
have immediate and-instructions with constants larger then 32 
bits.
like : And3(tmp37, val_1, BCValue(Imm64(18374686479671623680)));
which will cause the bytecode-interpreter to the 
immediate-bytecode instruction And tmp37, (immvalue & 0xFFFF_FFFF)
Which in this case will become And tmp37, #0 (since the lower 
bits of 18374686479671623680 are zero)

This is now fixed by pushing 64bit value into a register and 
issuing a reg-reg instruction.

So, you see, there is never a boring day in newCTFE-land :)

Cheers, Stefan


More information about the Digitalmars-d mailing list